Blazor父组件传参后子组件未更新问题(Fluxor状态管理)
问题:.NET8 Blazor WASM + Fluxor 状态更新后子组件UI不刷新
我在.NET8 Blazor WASM应用中用Fluxor做状态管理,父组件通过输入参数将Store中的状态传给子组件。分发RejectPerson动作后,Redux DevTools显示状态已更新,但子组件UI毫无变化。直接在子组件注入状态能正常工作,但我想搞懂通过输入参数传递时失效的原因。另外,触发LoadPeopleStateSuccess动作的Reducer能正常更新状态和UI,这点让我很困惑。
父组件代码
@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)] //移除人员 }; } //... } 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)); } } //... }
无效的尝试
我试过订阅RejectPersonSuccess动作并调用StateHasChanged()强制刷新,但没效果:
protected override void OnInitialized() { base.OnInitialized(); ActionSubscriber.SubscribeToAction<RejectPersonSuccess>(this, (action) => StateHasChanged()); }
对比:正常工作的Load动作代码
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 }; }
原因分析与解决方案
核心问题:参数绑定名称不匹配
你父组件给ShowPeople传递的参数是Requests,但子组件定义的接收参数是People——这就导致子组件根本没接收到父组件传递的状态数据,始终用的是默认的空数组。这就是为什么Redux DevTools显示状态更新,但子组件UI毫无变化的根本原因。
验证与修复
修正参数绑定名称:把父组件里的
Requests改成People,确保和子组件的参数名一致:<ShowPeople People="_state.Value.People.ToArray()"></ShowPeople>改完之后,状态更新时父组件会传递新的数组给子组件,Blazor检测到参数变化后就会更新子组件UI。
额外优化建议:
- 不要在
PeopleEffects里直接创建HttpClient,应该通过依赖注入获取,避免资源泄漏。 - 如果后续遇到类似的变更检测问题,可以在子组件中重写
ShouldRender方法强制返回true,不过这个场景下修正参数名就足够解决问题。
- 不要在
内容的提问来源于stack exchange,提问作者baouss
相关产品推荐
相关产品推荐

