Blazor Server中OnAfterRenderAsync执行后变量不更新、点击事件失效问题
问题根因
- 代码中
sNom = sessionStorage.GetItemAsync<string>("Nom").Result;使用Result同步阻塞异步调用,Blazor Server的同步上下文为单线程模型,该写法会直接触发线程死锁,后续所有UI交互事件(比如按钮点击的TestInc)都会被卡住无法触发。 - 读取完sessionStorage变量后没有手动触发状态更新,就算成功拿到值也不会自动渲染到页面上。
修复方案
第一步:修正OnAfterRenderAsync的异步调用逻辑
不要用.Result阻塞调用,所有sessionStorage操作都用await异步执行,读取完值后调用StateHasChanged()触发页面重绘:
@code { private int tutu = 0; public string sNom; // 需要用到跳转逻辑请先注入NavigationManager [Inject] private NavigationManager NavManager { get; set; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { bool isConnected = await sessionStorage.GetItemAsync<bool>("isConnected"); //if (!isConnected) //{ // NavManager.NavigateTo("/Login", forceLoad: true); //} // 改为await异步调用,移除Result sNom = await sessionStorage.GetItemAsync<string>("Nom"); // 触发状态更新,通知页面渲染sNom的值 StateHasChanged(); } await base.OnAfterRenderAsync(firstRender); } private void TestInc() { tutu += 1; } }
第二步:页面添加sNom渲染节点测试
可以在HTML部分新增展示读取到的用户名的代码:
@inject Blazored.SessionStorage.ISessionStorageService sessionStorage <button @onclick="TestInc">TEST</button> <h1>@tutu</h1> <!-- 新增sessionStorage读取结果展示 --> @if (!string.IsNullOrEmpty(sNom)) { <h2>当前登录用户:@sNom</h2> }
补充说明
- Blazor Server中禁止在异步生命周期方法里用
.Result或者.Wait()同步阻塞异步操作,必然会触发单线程同步上下文死锁,是导致按钮点击无响应的核心原因。 OnAfterRenderAsync的firstRender阶段是Blazor Server中最早可安全访问浏览器侧存储(sessionStorage、localStorage)的生命周期,此时页面已经和客户端完成交互通道建立,更早的生命周期阶段还未和浏览器连通,无法读取客户端存储。- 异步修改完组件的状态变量后,如果没有自动触发重绘,手动调用
StateHasChanged()即可通知UI更新。
内容的提问来源于stack exchange,提问作者CodingNewb
相关产品推荐
相关产品推荐

