Blazor 父级不更新 chilld

问题描述 投票:0回答:1

我正在使用 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
    };
}
redux blazor-webassembly fluxor
1个回答
0
投票

要解决此问题,您需要确保父组件在状态更改时正确触发 UI 刷新。你可以尝试这样做:

  1. 在父级中,查看您正在订阅状态更改并正确调用 StateHasChanged()。

  2. 确保状态订阅和方法调用设置正确,以便刷新 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; }
}
© www.soinside.com 2019 - 2024. All rights reserved.