[Blazor] Fluxor - Effects
- 웹 프로그래밍/Blazor
- 2022. 11. 15. 00:42
Effect란?
- Blazor Stores 에서는 State, Feature, Actions, Reducers 및 Effects 의 총 5가지 부분으로 구성되어 있습니다.
- 여기서 오늘은 Fluxor 에서 Effects 가 무엇인지에 대해서 알아보려고 합니다.
- Fluxor 에서 Effects 는 Dispatch 된 Action 이 순수하게 Reducer 방법으로 Store 외부의 리소스에 접근해야 할 때 사용됩니다.
- 일반적인 예는 API 에 HTTP 객체를 호출하는 것입니다.
- Reducer 메서드는 현재 상태 및 구독 중인 Action 만 접근할 수 있습니다.
- Effect 메서드는 외부 리소스에 액세스할 수 있으며, 새 상태를 방출하기 위해 Reducers에서 처리할 Acts 자체를 디스패치합니다.
- Effect 메서드를 포함하는 클래스는 인스턴스화 시 생성자를 통해 리소스를 주입할 수 있는 인스턴스 클래스(비정적)입니다.
- Blazor의 표준 종속성 주입 메커니즘을 사용하여 구성 요소에 주입할 수 있는 모든 것을 Effect 클래스 인스턴스에 주입할 수 있습니다.
예제 코드
- Effect 예제 코드는 Blazor Server 기본 프로젝트를 생성하게 되면 자동 생성되는 razor 중 하나인 일기예보 페이지를 대상으로 Effects 예제를 작성해 봅니다.
- 현재 Fluxor 를 도입하기 전에는
Fetch data
메뉴에서 다른 메뉴를 갔다가 돌아오면, 데이터가 Reset 되어 새로운 데이터가 표시되는 것을 확인할 수 있습니다. - Fluxor 를 이용하여 상태를 유지하고, Reset 버튼을 클릭할 때 새로운 데이터로 갱신되도록 코드 작성을 진행해 보겠습니다.
1. 상태 클래스 추가
- 그럼 이제 Fluxor 기능으로 하나씩 바꾸어 보도록 하겠습니다.
- 먼저, 날씨 정보 기능을 위한 State 클래스를 생성합니다.
using FluxExample.Data;
using Fluxor;
namespace FluxExample.Store.Weather;
public record WeatherState
{
public bool Initialized { get; init; }
public bool Loading { get; init; }
public WeatherForecast[]? Forecasts { get; init; }
}
public class WeatherFeature : Feature<WeatherState>
{
public override string GetName() => "Weather";
protected override WeatherState GetInitialState()
{
return new WeatherState
{
Initialized = false,
Loading = false,
Forecasts = Array.Empty<WeatherForecast>()
};
}
}
2. Action 클래스 추가
using FluxExample.Data;
using Fluxor;
namespace FluxExample.Store.Weather
{
public class WeatherSetInitializedAction
{
}
public class WeatherSetForecastsAction
{
public WeatherForecast[] Forecasts { get; }
public WeatherSetForecastsAction(WeatherForecast[] forecasts)
{
Forecasts = forecasts;
}
}
public class WeatherSetLoadingAction
{
public bool Loading { get; }
public WeatherSetLoadingAction(bool loading)
{
Loading = loading;
}
}
}
3. Reducer 클래스 추가
using Fluxor;
namespace FluxExample.Store.Weather;
public static class Reducers
{
[ReducerMethod]
public static WeatherState OnSetForecasts(WeatherState state, WeatherSetForecastsAction action)
{
return state with
{
Forecasts = action.Forecasts
};
}
[ReducerMethod]
public static WeatherState OnSetLoading(WeatherState state, WeatherSetLoadingAction action)
{
return state with
{
Loading = action.Loading
};
}
[ReducerMethod(typeof(WeatherSetInitializedAction))]
public static WeatherState OnSetInitialized(WeatherState state)
{
return state with
{
Initialized = true
};
}
}
4. Effect 추가
- 다음으로, Effects 를 추가하는 내용입니다.
- 앞서, OnSetForecasts, OnSetLoading, OnSetInitialized 총 3개의 Reducer 를 추가하였습니다.
- 해당 Reducer 는 FetchData 화면에서 Reset 버튼을 클릭할 시, 새롭게 Weather 데이터를 갱신하는 내용을 담고 있습니다.
- 이 내용을 바로 razor 페이지에서 사용할 수도 있지만, Effects 로 묶어서 한번에 호출을 할 수도 있습니다.
using FluxExample.Data;
using Fluxor;
namespace FluxExample.Store.Weather
{
public class WeatherLoadForecastsAction { }
public class WeatherEffects
{
private readonly WeatherForecastService ForecastService;
public WeatherEffects(WeatherForecastService rorecastService)
{
ForecastService = rorecastService;
}
[EffectMethod(typeof(WeatherLoadForecastsAction))]
public async Task LoadForecasts(IDispatcher dispatcher)
{
dispatcher.Dispatch(new WeatherSetLoadingAction(true));
var forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
dispatcher.Dispatch(new WeatherSetForecastsAction(forecasts));
dispatcher.Dispatch(new WeatherSetLoadingAction(false));
}
}
}
5. FetchData.razor 코드
- 그럼 이제,
FetchData.razor
파일에 Fluxor 를 사용하는 코드를 추가해 주면 됩니다.
@page "/fetchdata"
<PageTitle>Weather forecast</PageTitle>
@using FluxExample.Data
@using FluxExample.Store.Weather
@using static System.Net.WebRequestMethods
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from a service.</p>
@if (loading)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
<br/>
<button class="btn btn-outline-info" @onclick="LoadForecasts">Refresh Forecasts</button>
}
@code {
[Inject]
public IDispatcher? Dispatcher { get; set; }
[Inject]
public IState<WeatherState>? State { get; set; }
private WeatherForecast[]? forecasts => State!.Value.Forecasts;
private bool loading => State!.Value.Loading;
protected override async Task OnInitializedAsync()
{
if (State!.Value.Initialized == false)
{
await LoadForecasts();
Dispatcher!.Dispatch(new WeatherSetInitializedAction());
}
await base.OnInitializedAsync();
}
private async Task LoadForecasts()
{
Dispatcher!.Dispatch(new WeatherLoadForecastsAction());
}
}
728x90
'웹 프로그래밍 > Blazor' 카테고리의 다른 글
[Blazor] 매개변수 여러개인 경우 EventCallBack 을 이용한 부모-자식 Component 값 전달하는 방법 (0) | 2022.11.15 |
---|---|
[Blazor] EventCallBack 을 이용한 부모-자식 Component 값 전달하는 방법 (0) | 2022.11.15 |
[Blazor] 상태 관리 라이브러리 (0) | 2022.11.09 |
[Blazor] 페이저 버튼 구현 (0) | 2022.11.08 |
[Blazor] 동적 페이지 개수 구하기 (0) | 2022.11.06 |
이 글을 공유하기