为什么Blazor中调用StateHasChanged/InvokeAsync(StateHasChanged())不触发重渲染?
问题原因
你调用StateHasChanged仅会触发当前组件的重渲染逻辑,但绑定给Table组件的数据源没有做对应更新:
- 新增产品后你仅存储了接口返回的单条新增产品数据,没有加到Table绑定的产品列表集合里
- 删除产品后你仅修改了提示文本,没有把对应ID的产品从Table绑定的列表集合里移除
重渲染时Table读取的还是旧的列表数据,自然不会显示变更。你手动刷新浏览器相当于重新拉取了全量最新的产品列表,所以才能看到变化。
解决方案
根据你Table数据源的维护方式选对应方案即可:
方案1:当前组件维护Table绑定的产品列表
如果你的Table绑定的是当前组件里的列表字段(比如命名为ProductList),只需要在操作成功后手动更新列表,再触发重渲染即可。
修改后的代码示例:
public async Task HandleValidSubmit() { ReceivedProduct = new MyBlazorApp.Models.Product(); using (var httpClient = new HttpClient()) { StringContent content = new StringContent(JsonConvert.SerializeObject(ProductData), Encoding.UTF8, "application/json"); using (var response = await httpClient.PostAsync("https://localhost:7104/api/Products", content)) { string apiResponse = await response.Content.ReadAsStringAsync(); ReceivedProduct = JsonConvert.DeserializeObject<MyBlazorApp.Models.Product>(apiResponse); } } FormSubmitMessage = "Product Created"; // 新增:把新增的产品加入绑定的列表 ProductList.Add(ReceivedProduct); await InvokeAsync(StateHasChanged); } protected async Task Delete(int Id) { await client.DeleteAsync("api/products/" + Id); FormSubmitMessage = "Product with ID: " + Id + " is deleted."; // 新增:把删除的产品从绑定的列表移除 ProductList.RemoveAll(p => p.Id == Id); await InvokeAsync(StateHasChanged); }
方案2:Table组件内部维护自身数据源
如果你把产品列表的拉取逻辑封装在Table组件内部,就给Table组件加一个公开的刷新方法,操作成功后主动调用该方法让Table重新拉取最新数据即可。
步骤1:给Table组件加公开刷新方法
// Table组件内部代码 public async Task RefreshDataAsync() { // 重新拉取全量产品列表 ProductList = await client.GetFromJsonAsync<List<MyBlazorApp.Models.Product>>("api/products"); await InvokeAsync(StateHasChanged); }
步骤2:父组件引用Table并调用刷新方法
首先在父组件的razor部分给Table加引用:
<ProductTable @ref="_productTableRef" />
然后在操作成功后调用刷新:
// 父组件代码 private ProductTable _productTableRef; protected async Task Delete(int Id) { await client.DeleteAsync("api/products/" + Id); FormSubmitMessage = "Product with ID: " + Id + " is deleted."; // 调用Table的刷新方法 await _productTableRef.RefreshDataAsync(); }
内容的提问来源于stack exchange,提问作者Tassisto
相关产品推荐
相关产品推荐

