Loading...
Loading...
Make interactive Blazor components work correctly with prerendering. USE FOR fixing duplicate data loads, UI flicker during prerender-to-interactive handoff, null references during prerender, persisting state across prerender, disabling prerendering, excluding pages from interactive routing, or detecting whether a component is currently prerendering. DO NOT USE for choosing which render mode to use (see create-blazor-project) or general component authoring (see author-component).
npx skill4agent add dotnet/skills support-prerenderingOnInitializedAsyncOnAfterRenderAsyncAGENTS.md| Mode | Prerendering applies? |
|---|---|
| None (Static SSR) | No — there's no interactive handoff |
| Server | Yes |
| WebAssembly | Yes |
| Auto | Yes |
NoneOnInitializedAsync[PersistentState]@page "/forecasts"
@rendermode InteractiveServer
<h1>Weather</h1>
@if (Forecasts is null)
{
<p>Loading...</p>
}
else
{
@foreach (var f in Forecasts)
{
<p>@f.Date: @f.TemperatureC°C</p>
}
}
@code {
[PersistentState]
public WeatherForecast[]? Forecasts { get; set; }
protected override async Task OnInitializedAsync()
{
Forecasts ??= await ForecastService.GetForecastsAsync();
}
}??=@key@foreach (var item in items)
{
<ItemCard @key="item.Id" />
}PersistentComponentState@inject PersistentComponentState ApplicationState
@code {
private List<Order>? orders;
protected override async Task OnInitializedAsync()
{
ApplicationState.RegisterOnPersisting(PersistOrders);
if (!ApplicationState.TryTakeFromJson<List<Order>>("orders", out var restored))
{
orders = await OrderService.GetOrdersAsync();
}
else
{
orders = restored;
}
}
private Task PersistOrders()
{
ApplicationState.PersistAsJson("orders", orders);
return Task.CompletedTask;
}
}[PersistentState]@rendermode @(new InteractiveServerRenderMode(prerender: false))InteractiveServerRenderModeInteractiveWebAssemblyRenderModeInteractiveAutoRenderMode<MyChart @rendermode="new InteractiveServerRenderMode(prerender: false)" />App.razor<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" /><Routes>HttpContext[ExcludeFromInteractiveRouting]@page "/privacy"
@attribute [ExcludeFromInteractiveRouting]
<h1>Privacy Policy</h1>HttpContextApp.razor<!DOCTYPE html>
<html>
<head>
<HeadOutlet @rendermode="RenderModeForPage" />
</head>
<body>
<Routes @rendermode="RenderModeForPage" />
<script src="_framework/blazor.web.js"></script>
</body>
</html>
@code {
[CascadingParameter]
public HttpContext HttpContext { get; set; } = default!;
private IComponentRenderMode? RenderModeForPage =>
HttpContext.AcceptsInteractiveRouting() ? InteractiveServer : null;
}InteractiveServerRendererInfoprotected override async Task OnInitializedAsync()
{
if (RendererInfo.IsInteractive)
{
// Only runs during the interactive render, not during prerender
await StartSignalRConnection();
}
}RendererInfoIsInteractivefalsetrueName"Static""Server""WebAssembly".ClientProgram.csIWebAssemblyHostEnvironmentProgram.cspublic MyComponent(IMyService? svc = null).ClientOnInitializedAsyncOnAfterRenderAsync(firstRender)OnInitializedAsync[PersistentState]??=HttpContext[ExcludeFromInteractiveRouting][PersistentState]