【问题标题】:Refresh blazor server child component from parent component by using StateHasChanged使用 StateHasChanged 从父组件刷新 Blazor 服务器子组件
【发布时间】: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"

标签: c# .net-core blazor blazor-server-side


【解决方案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; 解决了所有更新问题。
猜你喜欢
  • 2019-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-01
  • 2023-02-17
  • 2021-01-23
  • 2022-01-13
相关资源
最近更新 更多