使用 StateHasChanged 从父组件刷新 Blazor 服务器子组件

Posted

技术标签:

【中文标题】使用 StateHasChanged 从父组件刷新 Blazor 服务器子组件【英文标题】:Refresh blazor server child component from parent component by using StateHasChanged 【发布时间】:2021-10-13 15:03:56 【问题描述】:

Blazor 重新加载子组件

我的一个组件如下所示(在我的例子中这是一个子组件)

ListMetaData 组件/子组件

  <table>
        bind the list of items from model to the table
  </table>

@code 
   
    List<MetaDataViewModel> model= new List<MetaDataViewModel>();    
    
    protected override async Task OnInitializedAsync()
    
        await LoadMetaDataList();
    
    public async Task  LoadMetaDataList()
            
        model= dbContextService.fetchFromDb();
        
    public void Refresh()
    
        StateHasChanged();
    

我有一个父组件,如下所示

@page "/settings/metadata"
@inject IDialogService DialogService
@inject ISnackbar Snackbar
<MudGrid>
<MudItem  >
   <MudButton OnClick="@((e) => AddNewmetaDataEvent())" 
    Class="ma-1">Add new</MudButton>
</MudItem>
<MudItem xs="12" >
    <ListMetaData  @ref="_listComponent" ></ListMetaData>
</MudItem>
</MudGrid>
@code 
     private ListMetaData  _listComponent;
    async Task AddNewmetaDataEvent()
    
        var dialog = DialogService.Show<AddMetaDataDialog>("Add new MetaData");
        var result = await dialog.Result;
        if (!result.Cancelled)
                   
             Snackbar.Add("Please wait while the list is getting updated", Severity.Info);
             _listComponent.Refresh();             
        
        else
        
              Snackbar.Add("Dialog cancelled without performing any action", Severity.Normal);
        
    

按钮点击事件的父组件会出现一个对话框,允许用户向数据库添加新项目。

在关闭对话框时,我正在尝试重新加载子组件中的项目列表

但即使在使用 StateHasChanged() 之后,我的列表也没有更新。我必须重新加载页面才能看到子组件中修改后的项目列表

我关注了来自社区 How to refresh a blazor sub/child component within a main/parent component? 的几个答案,但没有得到我的代码中不正确的地方

【问题讨论】:

您已将 AddNewmetaDataEvent 方法包装在 async void 结构中。只需使用OnClick="AddNewmetaDataEvent" 【参考方案1】:

这应该可以(但是请参阅注释)

@page "/settings/metadata"
@inject IDialogService DialogService
@inject ISnackbar Snackbar

 <MudItem  >
   <MudButton OnClick="@((e) => AddNewmetaDataEvent())" 
    Class="ma-1">Add new</MudButton>
 </MudItem>

@if (_updating)

<span>Updating</span>

else
    
<MudGrid>

   <MudItem xs="12" >
    <ListMetaData  @ref="_listComponent" ></ListMetaData>
</MudItem>
</MudGrid>        
 



@code 
    private ListMetaData  _listComponent;
    private bool _updating;
    async Task AddNewmetaDataEvent()
    
        _updating = true; // forces UI dom refresh

        var dialog = DialogService.Show<AddMetaDataDialog>("Add new MetaData");
        var result = await dialog.Result;
        if (!result.Cancelled)
                   
             Snackbar.Add("Please wait while the list is getting updated", Severity.Info);
        
        else
        
              Snackbar.Add("Dialog cancelled without performing any action", Severity.Normal);
        
        _updating = false; // forces UI dom refresh
    

尽量避免通过捕获引用来更新子组件。我知道像 SyncFusion 等 UI 库会强制使用这种 @ref / Refresh() 模式。尽可能避免它,而是将数据作为参数传递。这将使您免于这些类型的手动刷新。

【讨论】:

将数据作为参数传递给子组件?在我的情况下,子组件用于显示列表以及我们必须传递什么参数?决定是否重新加载的标志?同样在答案中,我们是否需要调用 Refresh()?我看不到任何地方都提到过 在 if ... else 语句中,渲染块之一。当 'updating' 标志为真时,MudGrid 组件将从 DOM 中移除。当它设置为 false 时,将从头开始渲染 MudGrid 组件。所以你不需要手动刷新任何东西。此外,在 ChildComponent 问题上,您应该将 List 发送到您的子组件。 (我正在稍微更新答案,因为它可能会导致运行时问题。) 我同意这个答案,await LoadMetaDataList(); 不应该在 ListMetaData 组件中,而应该在父组件中。然后&lt;ListMetaData data=listData /&gt; 解决了所有更新问题。

以上是关于使用 StateHasChanged 从父组件刷新 Blazor 服务器子组件的主要内容,如果未能解决你的问题,请参考以下文章

Blazor 组件在 StateHasChanged() 之后未更新

从父 React 刷新子状态

Blazor 中的 StateHasChanged() 与 InvokeAsync(StateHasChanged)

Blazor 中的 StateHasChanged 目标

在子组件中使用Echarts图表无法刷新显示的问题(解决:子组件刷新)

在子组件中使用Echarts图表无法刷新显示的问题(解决:子组件刷新)