调用Action事件时StateHasChanged未触发Blazor组件渲染问题
问题解决:Blazor组件订阅事件后UI未重新渲染
核心问题分析
- StateHasChanged执行上下文错误:直接绑定
StateHasChanged到事件,当事件从非组件上下文触发时,无法正确触发UI渲染,需通过InvokeAsync确保在Blazor组件的同步上下文执行。 - 组件状态未更新:OgSidebar的
_isSidebarToggled字段仅在初始化时获取值,事件触发后未重新拉取最新的本地存储值,导致UI绑定的仍是旧状态。
修复步骤
1. 修正OgSidebar.razor.cs的事件处理逻辑
替换直接绑定StateHasChanged的方式,改为自定义事件处理方法,重新获取最新状态并通过InvokeAsync触发渲染:
protected override void OnInitialized() { StorageManagerService.OnChange += HandleStorageChange; } protected override async Task OnInitializedAsync() { var containsKey = await StorageManagerService.ContainsKeyAsync("isSidebarToggled"); if (containsKey == false) await StorageManagerService.SetItemAsync("isSidebarToggled", true); _isSidebarToggled = await StorageManagerService.GetItemByKeyAsync<bool>("isSidebarToggled"); } private async void HandleStorageChange() { // 重新获取本地存储的最新状态 _isSidebarToggled = await StorageManagerService.GetItemByKeyAsync<bool>("isSidebarToggled"); // 在组件上下文执行渲染操作 await InvokeAsync(StateHasChanged); } public void Dispose() { StorageManagerService.OnChange -= HandleStorageChange; }
2. 完善StorageManagerService的事件触发逻辑
添加事件null检查,避免无订阅者时触发事件引发空引用异常:
private readonly ILocalStorageService _localStorageService; public event Action OnChange; public async Task<T> GetItemByKeyAsync<T>(string identifier) { var itemFromLocalStorage = await _localStorageService.GetItemAsync<T>(identifier); return itemFromLocalStorage; } public async Task<bool> ContainsKeyAsync(string identifier) { return await _localStorageService.ContainKeyAsync(identifier); } public async Task SetItemAsync<T>(string identifier, T item) { await _localStorageService.SetItemAsync(identifier, item); // 检查事件是否有订阅者,再触发 OnChange?.Invoke(); }
3. 移除OgToolbar中不必要的事件订阅
OgToolbar仅负责触发状态修改,无需订阅OnChange事件(除非自身需要更新UI),可移除相关代码:
[Inject] private IStorageManagerService StorageManagerService { get; set; } private bool _isSidebarToggled = false; protected override async Task OnInitializedAsync() { var containsKey = await StorageManagerService.ContainsKeyAsync("isSidebarToggled"); if (containsKey == false) await StorageManagerService.SetItemAsync("isSidebarToggled", true); _isSidebarToggled = await StorageManagerService.GetItemByKeyAsync<bool>("isSidebarToggled"); }
修复原理
InvokeAsync(StateHasChanged):确保渲染操作在Blazor组件的同步上下文执行,避免跨线程调用导致的渲染失效。- 重新获取
_isSidebarToggled值:保证组件状态与本地存储数据一致,UI绑定的是最新状态。 - 事件null检查:提升代码健壮性,防止无订阅者时触发事件引发异常。
内容的提问来源于stack exchange,提问作者Mohammed Alwedaei
相关产品推荐
相关产品推荐

