Search code examples
.netasp.net-coreblazorblazor-server-side

Preventing double rendering with the combination of "Interactive Server Render Mode" and "Stream Rendering"


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:

  • I'm I right, that the second rerender occurs because the circuit connection to the server is established?
  • Is there a way to prevent the second rerender?

Solution

  • 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
    

    Docs