Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 49 additions & 30 deletions aspnetcore/blazor/components/prerendering-and-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -732,25 +732,9 @@ For more information, see <xref:blazor/components/index#namespaces>.

## Preserve prerendered state

Without preserving prerendered state, any state that used during prerendering is lost and must be recreated when the app is fully loaded. If any state is setup asynchronously, the UI may flicker as the prerendered UI is replaced with temporary placeholders and then fully rendered again.
Without preserving prerendered state, state used during prerendering is lost and must be recreated when the app is fully loaded. If any state is setup asynchronously, the UI may flicker as the prerendered UI is replaced with temporary placeholders and then fully rendered again.

To solve these problems, Blazor supports persisting state in a prerendered page using the [Preserve Component State Tag Helper](xref:mvc/views/tag-helpers/builtin-th/preserve-component-state-tag-helper) (`<preserve-component-state />`). Add the `<preserve-component-state />` tag inside the closing `</body>` tag of `_Layout.cshtml`.

::: zone pivot="webassembly"

`Pages/_Layout.cshtml`:

```cshtml
<body>
...

<persist-component-state />
</body>
```

::: zone-end

::: zone pivot="server"
To solve these problems, Blazor supports persisting state in a prerendered page using the [Preserve Component State Tag Helper](xref:mvc/views/tag-helpers/builtin-th/preserve-component-state-tag-helper) (`<preserve-component-state />`). Add the `<preserve-component-state />` tag inside the closing `</body>` tag.

`Pages/_Layout.cshtml`:

Expand All @@ -762,32 +746,67 @@ To solve these problems, Blazor supports persisting state in a prerendered page
</body>
```

::: zone-end
In the app, decide what state to persist using the `PersistentComponentState` service. The `PersistentComponentState.RegisterOnPersisting` event is fired just before the state is persisted into the prerendered page, which allows a component to retrieve the state when initializing the component.

In the app, decide what state to persist using the `ComponentApplicationState` service. The `ComponentApplicationState.OnPersisting` event is fired just before the state is persisted into the prerendered page, which allows a component to retrieve the state when initializing the component.

The following example shows how the weather forecast in the `FetchData` component from an app based on the Blazor project template is persisted during prerendering and then retrieved to initialize the component. The Persist Component State Tag Helper persists the component state after all component invocations.
The following example shows how the weather forecast in the `FetchData` component from a hosted Blazor WebAssembly app based on the Blazor project template is persisted during prerendering and then retrieved to initialize the component. The Persist Component State Tag Helper persists the component state after all component invocations.

`Pages/FetchData.razor`:

```razor
@page "/fetchdata"
@implements IDisposable
@inject ComponentApplicationState ApplicationState
@using BlazorSample.Shared
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState

<h1>Weather forecast</h1>

...
<p>This component demonstrates fetching data from the server.</p>

@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}

@code {
private WeatherForecast[] forecasts;
private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
private PersistingComponentStateSubscription _persistingSubscription;

protected override async Task OnInitializedAsync()
{
ApplicationState.OnPersisting += PersistForecasts;
_persistingSubscription = ApplicationState.RegisterOnPersisting(PersistForecasts);

if (!ApplicationState
.TryTakeAsJson<WeatherForecast[]>("fetchdata", out forecasts))
if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>("fetchdata", out var restored))
{
forecasts = await WeatherForecastService.GetForecastAsync(DateTime.Now);
}
else
{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
forecasts = restored!;
}
}

Expand All @@ -800,7 +819,7 @@ The following example shows how the weather forecast in the `FetchData` componen

void IDisposable.Dispose()
{
ApplicationState.OnPersisting -= PersistForecasts;
_persistingSubscription.Dispose();
}
}
```
Expand Down