首页 > 解决方案 > Blazor StateHasChanged() 未更新子组件

问题描述

我有一个包含项目目录的服务。这些项目取决于服务的活跃公司。

// Tell Service to refresh in context of Company 1
await Service.SetActiveCompany(1);
// Get Catalog (which will be in the context of Company 1)
Catalog catalog = Service.Catalog;

// Tell Service to refresh in context of Company 2
await Service.SetActiveCompany(2);
// Get Catalog (which will be in the context of Company 2)
catalog = Service.Catalog;

以上单独工作正常。目录更新为来自相应公司的项目。

在我的应用程序中,我有一个布局,其中包括选择活跃公司的下拉菜单。当这种情况发生变化时,我会调用:

await Service.SetActiveCompany(dropdown.selectedCompanyId);

在服务中,我刷新目录并引发事件

public class CompanyChangedEventArgs : EventArgs { }
public class Service
{
    public event EventHandle<CompanyChangedEventArgs> CompanyChanged;
    protected void OnCompanyChanged() 
        => CompanyChanged?.Invoke(this, new CompanyChangedEventArgs());
    public Catalog Catalog { get; private set; }
    public async Task SetActiveCompany(int companyId)
    {
        Catalog = await API.GetCatalogForCompany(companyId);
        OnCompanyChanged();
    }
}

在父组件中(使用上面的布局)我捕捉到事件

<CatalogSectionA />
<CatalogSectionB />
@code {
   protected override void OnInitialized()
   {
       Service.CompanyChanged += HandleCompanyChanged;
       base.OnInitialized();
   }
   HandleCompanyChanged(object sender, EventArgs e) => StateHasChanged();
}

我希望这会导致 CatalogSectionA 和 CatalogSectionB 组件刷新。

目录A部分

<div>
  @foreach (Item i in Catalog.SectionA.Items)
  {
    <div>@i.Name</div>
  }
</div>
@code {
  Catalog Catalog => Service.Catalog;
}

目录B部分

<div>
  @foreach (Item i in Catalog.SectionB.Items)
  {
    <div>@i.Name</div>
  }
</div>
@code {
  Catalog Catalog => Service.Catalog;
}

我曾期望在父组件中调用 StateHasChanged() 来强制重新渲染 CatalogSectionA 和 CatalogSectionB,但事实并非如此。

我可以在每个上放置一个 Refresh 方法,并在处理公司变更事件时从父级调用这些方法,但我认为 Blazor 没有必要这样做,StateHasChanged() 可以解决问题吗?

标签: asp.net-coreblazorblazor-webassembly

解决方案


在子组件上放置一个“冗余”级联参数后它就可以工作了。

根本没有传递任何参数,因为状态(参数)正在服务中进行管理,我期待 StateHasChanged() 提示子组件重新渲染并返回服务。

所以,我的结论是,如果我在父组件上调用 StateHasChanged(),那么只有在 Blazor 检测到子组件中对父组件更改的“依赖”时,子组件才会重新呈现。

如果没有依赖项(即没有参数或级联参数),那么看起来 Blazor 假定当父组件中的状态发生更改时,子组件中不需要更改。


推荐阅读