I'm facing a non-deterministic state loss issue in a Blazor WebAssembly (.NET 6) app that only happens after a specific sequence of async JS interop + navigation + re-render.
Scenario
- Blazor WebAssembly (.NET 6)
- Hosted model
Scopedservice used as a client-side state container- Async JS interop call (
IJSRuntime.InvokeAsync) - Navigation via
NavigationManager.NavigateTo - Components use
OnInitializedAsyncandOnAfterRenderAsync
Problem
A scoped service randomly loses its state after navigation only when:
- A JS interop call is awaited
- Followed by navigation
- And a component re-renders during the same render cycle
This does NOT happen consistently, which makes it extremely hard to debug.
Service:
public class AppState{ public Guid SessionId { get; set; } = Guid.NewGuid(); public string? CurrentUser { get; set; }}Registered as:
builder.Services.AddScoped<AppState>();Component A:
@inject AppState AppState@inject IJSRuntime JS@inject NavigationManager Nav<button @onclick="HandleClick">Go</button>@code { private async Task HandleClick() { await JS.InvokeVoidAsync("console.log", AppState.SessionId); // After this navigation, AppState is SOMETIMES reset Nav.NavigateTo("/pageB"); }}Component B:
@inject AppState AppState<p>Session: @AppState.SessionId</p>@code { protected override void OnInitialized() { // Sometimes a NEW Guid appears here Console.WriteLine(AppState.SessionId); }}Observed behavior:
SessionIdshould remain constant- Occasionally, a new Guid is generated, as if:
- The scoped service was recreated
- Or the DI scope was reset
- No page reload occurs
- No
forceLoad: true - Happens more frequently when:
- Network throttling is enabled
- Browser tab loses focus
- Rendering is heavy (Virtualize / large DOM)
What I've verified:
- ✔ No
AddTransient - ✔ No
forceLoadnavigation - ✔ No page refresh
- ✔ Same browser tab
- ✔ No manual service recreation
- ✔ Happens only in WebAssembly (not Server)
Questions
- Under what internal conditions does Blazor WebAssembly recreate the DI scope?
- Can async JS interop cause a render boundary that resets scoped services?
- Is this related to the single-threaded WebAssembly synchronization context?
- Is there a known issue where navigation during
awaitcauses service re-instantiation? - What is the correct pattern for guaranteed client-side state persistence in Blazor WASM?