我正在使用 Fluxor 为我的 NET8 Blazor WASM 应用程序进行状态管理。我的父组件通过输入参数将状态从存储传递到子组件。
家长
@page "/people"
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
@inject IState<PeopleState> _state
<ShowPeople Requests="_state.Value.People.ToArray()"></ShowPeople>
孩子
@foreach(var person in People)
{
<div>@person.Name</div>
}
@code {
[Parameter] public Person[] People { get; set; } = [];
}
状态摘录
public record PeopleState
{
public bool IsLoading { get; init; }
public bool IsLoaded { get; init; }
public string? Error { get; init; }
public DateTimeOffset LoadedAt { get; init; }
public List<Person> People { get; init; } = [];
}
public class PeopleFeatureState : Feature<PeopleState>
{
public override string GetName() => nameof(PeopleState);
protected override PeopleState GetInitialState() => new();
}
public record RejectPerson(string Id);
public record RejectPersonSuccess(string Id);
public record RejectPersonFailure(string Error);
//...
public static class PeopleReducer
{
[ReducerMethod] public static PeopleState HandleRejectPerson(PeopleState state, RejectPerson _)
{
return state with { IsLoading = true };
}
[ReducerMethod] public static PeopleState HandleRejectPersonFailure(PeopleState state, RejectPersonFailure action)
{
return state with
{
IsLoading = false,
Error = action.Error
};
}
[ReducerMethod] public static PeopleState HandleRejectPersonSuccess(PeopleState state, RejectPersonSuccess action)
{
return state with
{
IsLoading = false,
People = [.. state.People.Where(u => u.Id != action.Id)] //remove person
};
}
//...
}
public class PeopleEffects(IState<PeopleState> state)
{
[EffectMethod] public async Task OnRejectPerson(RejectPerson action, IDispatcher dispatcher)
{
string id = action.Id;
try
{
var http = new HttpClient();
HttpResponseMessage resp = await http.DeleteAsync($"people/{id}");
if (!resp.IsSuccessStatusCode)
{
throw new ApplicationException("error");
}
dispatcher.Dispatch(new RejectPersonSuccess(id));
}
catch (Exception ex)
{
dispatcher.Dispatch(new RejectPersonFailure(ex.Message));
}
}
//...
}
状态是可以批准或拒绝的人员列表(用户注册)。当调度
RejectPerson
操作时,我可以在 Redux DevTools 中看到它发生,并且状态也会更新。但在 UI 中子组件不会改变。
我也尝试在显式侦听相关事件时强制刷新,但也不起作用。
protected override void OnInitialized()
{
base.OnInitialized();
ActionSubscriber.SubscribeToAction<RejectPersonSuccess>(this, (action) => StateHasChanged());
}
虽然我知道,我可以将状态注入到子级中并且这有效,但我需要理解为什么它在使用输入参数时不起作用。有什么想法吗?
让我完全困惑的是,触发以下减速器的操作会正确更新状态和 UI。 LoadPeopleStateSuccess 往返数据库并获取所有数据。基本上与加载父级时所做的相同。
public record LoadPeopleState(bool Force = false);
public record LoadPeopleStateSuccess(Person[] People);
[ReducerMethod] public static PeopleState HandleLoadPeopleStateSuccess(PeopleState state, LoadPeopleStateSuccess action)
{
return state with
{
IsLoading = false,
IsLoaded = true,
People = [.. action.People],
LoadedAt = DateTimeOffset.UtcNow
};
}
要解决此问题,您需要确保父组件在状态更改时正确触发 UI 刷新。你可以尝试这样做:
在父级中,查看您正在订阅状态更改并正确调用 StateHasChanged()。
确保状态订阅和方法调用设置正确,以便刷新 UI。
您可以尝试以下方法:
家长
@page "/parent"
@inject IState<MyState> State
<ChildComponent StateData="State.Value"></ChildComponent>
@code {
protected override void OnInitialized()
{
State.StateChanged += OnStateChanged;
}
private void OnStateChanged()
{
InvokeAsync(StateHasChanged);
}
}
孩子
@code {
[Parameter]
public MyState StateData { get; set; }
}