You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用Action事件时StateHasChanged未触发Blazor组件渲染问题

问题解决:Blazor组件订阅事件后UI未重新渲染

核心问题分析

  1. StateHasChanged执行上下文错误:直接绑定StateHasChanged到事件,当事件从非组件上下文触发时,无法正确触发UI渲染,需通过InvokeAsync确保在Blazor组件的同步上下文执行。
  2. 组件状态未更新: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 18:06:32