Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net core Blazor StateHasChanged()未更新子组件_Asp.net Core_Blazor_Blazor Webassembly - Fatal编程技术网

Asp.net core Blazor StateHasChanged()未更新子组件

Asp.net core Blazor StateHasChanged()未更新子组件,asp.net-core,blazor,blazor-webassembly,Asp.net Core,Blazor,Blazor Webassembly,我有一个包含项目目录的服务。这些项目取决于服务的活跃公司 // 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

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

// 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;
上述方法单独使用效果良好。目录将使用相应公司的项目刷新

// 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();
    }
}
公共类CompanyChangedEventArgs:EventArgs{}
公务舱服务
{
公共事件处理公司变更;
受保护的无效OnCompanyChanged()
=>CompanyChanged?.Invoke(这是新的CompanyChangedEventArgs());
公共目录{get;private set;}
公共异步任务SetActiveCompany(int companyId)
{
Catalog=wait API.GetCatalogForCompany(companyId);
OnCompanyChanged();
}
}
在父组件中(使用上面的布局),我捕获事件

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

@代码{
受保护的覆盖无效OnInitialized()
{
Service.CompanyChanged+=HandleCompanyChanged;
base.OnInitialized();
}
HandleCompanyChanged(对象发送方,EventArgs e)=>StateHasChanged();
}
我希望这会导致CatalogSectionA和CatalogSectionB组件刷新

目录部分A

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

@foreach(目录A部分项目中的项目i)
{
@i、 名字
}
@代码{
Catalog=>Service.Catalog;
}
目录B部分

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

@foreach(目录B节项目中的项目i)
{
@i、 名字
}
@代码{
Catalog=>Service.Catalog;
}
我曾期望在父组件中调用StateHasChanged()以强制重新呈现CatalogSectionA和CatalogSectionB,但事实并非如此


在处理公司变更事件时,我可以在每个组件上放置一个刷新方法,并从父级调用这些方法,但我认为Blazor不需要这样做,StateHasChanged()可以做到这一点。

在其工作的子组件上放置了一个“冗余”级联参数

在服务中管理状态(参数)时,根本没有传递任何参数,我希望StateHasChanged()会提示子组件重新呈现并返回服务

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


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

您可以尝试在
InvokeAsync
中调用
StateHasChanged
?例如,
HandleCompanyChanged(…)=>InvokeAsync(()=>StateHasChanged())
试一试。并且还尝试使HandleCompanyChanged异步并“等待”InvokeAsync调用,但没有更改。我应该澄清,我上面的代码是我认为能够显示问题的最小代码。实际上,对SetActiveCompany的调用是异步的,因为它调用了API async。这是否改变了对原始问题的分析?更新了问题以反映这一点。啊,之前读得不够;在父组件中调用
StateHasChanged
,不会导致子组件重新渲染。那将非常昂贵。更改的状态仅适用于当前组件,以便组件检查是否需要重新渲染任何内容。由于子组件从外部看仍然相同(没有参数更改或任何更改),因此父组件不会导致子组件重新渲染我建议您将
目录作为参数传递给孩子们。这将使数据流更加明确,并将解决您的问题。谢谢您的确认,@poke。我的目标是将目录作为所有需要它的子组件的级联值向下传递,而不是让子组件直接从服务获取它。很高兴听到第二种意见,证实这种方法是有意义的。谢谢你的帮助。是的,你是对的。设置参数值会触发子级上的
SetParametersAsync
,调用
StateHasChanged
是该过程的一部分。有一种替代方法,取决于您的服务范围。如果它的作用域是有限的,那么每个需要了解
CompanyChanged
事件的组件都会注入服务-它都是相同的对象实例-为事件注册,然后在事件处理程序中调用
StateHasChanged