【问题标题】:Blazor Appstate doesn't update ChildComponentBlazor Appstate 不更新 ChildComponent
【发布时间】:2021-11-18 14:35:42
【问题描述】:

尝试使用 AppState 类传递变量,当调用发生在同一个组件中时,组件会更新,但在父级触发事件时不会在子组件中。

家长

@code {
    [Parameter]
    public int Id { get; set; }

    WikiDetailDto wikiDetail = null;

    protected async override Task OnInitializedAsync()
    {
        Console.WriteLine("going in detail INIT");
        AppState.OnCurrentWikiPageChanged += StateHasChanged;
        AppState.SetCurrentWikiPage(await wikiPageService.GetDetail(Id));
        wikiDetail = AppState.CurrentWikiPage;

        Console.WriteLine("Retrieved WikiDetail!");
    }
}

儿童

<MudDrawer Anchor="Anchor.End" Open="true">
    <MudDrawerHeader>Recommendations</MudDrawerHeader>
    @if(AppState.CurrentWikiPage != null)
    {
        @(RecommendedWikiPages = CalculateReccomendedWikis(AppState.CurrentWikiPage));
        if(RecommendedWikiPages != null)
        {
            foreach(var p in RecommendedWikiPages)
            {
                <MudCard>
                    <MudCardContent>
                        <MudText>@p.Name</MudText>

                    </MudCardContent>
                </MudCard>
            }
        }
    }
    else
    {
        <p>Loading...</p>
    }

当 AppState.CurrentWikiPage 更新时,它不会检查 cild 的 if 语句。 这里的最佳做法是什么?我不想使用级联值。

AppState

public WikiDetailDto CurrentWikiPage { get; set; }
        public event Action OnCurrentWikiPageChanged;
        public void SetCurrentWikiPage(WikiDetailDto wikiPage)
        {
            CurrentWikiPage = wikiPage;
            OnCurrentWikiPageChanged?.Invoke();
        }

【问题讨论】:

  • 你能不使用 eventCallback 吗?
  • 看看这个项目,它是您想要实现的目标的实现,但不必为每个组件或属性注册 Changed 事件。 github.com/dagmanolis/Blaast

标签: c# .net blazor blazor-webassembly


【解决方案1】:

如果我正确阅读了您的代码,则子组件需要注册OnCurrentWikiPageChanged 事件。

您的孩子需要看起来像这样:

@implements IDisposable
..... markup code


    protected async override Task OnInitializedAsync()
    {
        AppState.OnCurrentWikiPageChanged += StateHasChanged;
    }

    public void Dispose()
    {
        AppState.OnCurrentWikiPageChanged -= StateHasChanged;
    }

我个人不会将StateHasChanged 直接链接到事件处理程序。这是不好的做法,因为StateHasChanged 必须运行 UI 上下文线程。如果事件调用者在另一个线程上运行,你会得到一个异常。我会坚持使用标准的EventHandler。 WASM 现在可能是单线程的,但可能不会永远。

我的处理程序看起来像:

private void OnxxxChanged(object sender, EventArgs e)
      => this.InvokeAsync(StateHasChanged);

【讨论】:

  • “这是不好的做法,因为 StateHasChanged 必须运行 UI 上下文线程。”让我把它说成politely,这不是一个坏习惯,这是一个好习惯,它确实在 UI 上下文线程中运行(至少目前是这样)。 “WASM 现在可能是单线程的,但它可能不会永远存在。”是的...这就是为什么您应该像这样调用 StateHasChanged 方法的原因:InvokeAsync (() =&gt; StateHasChanged); 现在,无论使用多少线程,`ExecutionContext` 都不会有任何问题。 “我会坚持使用标准的 EventHandler。”
  • 在我看来,当涉及到简单的事情时,这是正确的方法,但是如果您像他一样管理应用程序状态,那么实现应用程序状态模式和观察者模式的服务是可行的选择。对不起我的错觉。我不会再这样做了,我会支持你的回答;}
  • @enet。没问题,我不生气。您不能保证事件委托的所有调用者总是在 UI 线程上运行——一个很好的例子是服务器页面中的计时器。因此,我认为将您的事件处理程序直接指向 StateHasChanged 是一种不好的做法,因为如果您一直这样做,有一天它会咬您或维护您的代码的人。我自己使用 `InvokeAsync 代码模式 - 带和大括号的方法。这里的问题是你提供的建议有多深。在许多情况下,我们最终会为人们重新编写大量代码! :-)
猜你喜欢
  • 2021-10-09
  • 2021-01-05
  • 1970-01-01
  • 2020-10-03
  • 1970-01-01
  • 2021-03-03
  • 2021-09-27
  • 1970-01-01
  • 2021-10-31
相关资源
最近更新 更多