Reputation: 530
I'm exploring the new Blazor features of .NET 8 and I'm encountering an issue where my component seems to be rendering twice. The issue occurs when I'm using "Stream Rendering" combined with the "Interactive Server Render Mode".
I've simplified my code for clarity:
@attribute [StreamRendering]
@rendermode InteractiveServer
@if (data == null)
{
<p>Loading...</p>
}
else
{
<p>@data</p>
}
@code {
private string? data;
protected override async Task OnInitializedAsync()
{
await Task.Delay(1000);
data = "Hello World!";
}
}
In this code, I expect the "Loading..." text to be displayed initially, and then, after a delay, the text "Hello World!" should replace it. This works, but as soon as the data
gets shown, the component rerenders and the loading text gets shown again.
My questions are:
Upvotes: 6
Views: 5084
Reputation: 813
I had the same thing, i "solved it" by not using the [Streamrendering] when using interactive server and loading my data like this:
@code
{
private string? data;
protected override async Task OnInitializedAsync()
{
_ = Init();
}
private async Task Init(){
await Task.Delay(1000);
data = "Hello World!";
}
}
This runs the init in another thread. It sends the html to the client. and the other thread updates the data using the interactive server mode. 2 notes:
Don't know if this is the most preferred way but works for me.
Upvotes: 0
Reputation: 14613
You can prevent the first render or tell the render engine not to clear the initial data with data-permanent
attribute on the element containing the data, this will give the perception of not being rendered twice. Docs
All interactive modes render on the server first, the client is sent html. This normally is a good thing the client sees updates almost instantly. To prevent the "Pre Render" use the prerender parameter on the constructor.
CustomRenderModes.cs
public static class CustomRenderModes
{
public static readonly InteractiveAutoRenderMode InteractiveAutoRenderModeNoPreRender
= new InteractiveAutoRenderMode(prerender: false);
public static readonly InteractiveServerRenderMode InteractiveServerRenderModeNoPreRender
= new InteractiveServerRenderMode(prerender: false);
public static readonly InteractiveWebAssemblyRenderMode InteractiveWebAssemblyRenderModeNoPreRender
= new InteractiveWebAssemblyRenderMode(prerender: false);
}
_imports.razor
@using static {NamespaceOfStaticModelHere}.CustomRenderModes
You can use @(new InteractiveWebAssemblyRenderMode(prerender: false))
directly on your component. The method I have shown with the static class is the same as how MS setup the initial 3 rendermodes with prerender. Source
SomeComponent.razor
@page "/thread/{ThreadId}"
@attribute [Authorize]
@rendermode InteractiveWebAssemblyRenderModeNoPreRender
Upvotes: 6
Reputation: 61
@attribute [StreamRendering]
@rendermode @(new InteractiveServerRenderMode(prerender: false))
Upvotes: 5
Reputation: 241
Ran into same behavior where a Blazor 8 WASM component set to @rendermode InteractiveAuto
renders twice on every state refresh. I was able to streamline the behavior to rendering just once by changing "@rendermode InteractiveAuto" to @rendermode @(new InteractiveAutoRenderMode(prerender: false))
at the top of the component. You can refer to the documentation from Microsoft.
Still researching the exact tradeoffs of adding that change, but it does work.
Upvotes: 0