0
votes

If I've understood Blazor Server correctly, when the browser makes the initial HTTP request Blazor Server will return the "dehydrated" HTML for the requested page.

The browser will show the HTML and then initiate the SignalR connection. Once the SignalR connection is in place the Blazor Server is then wired up to the HTML and all works (hydrated).

I believe there is a state in which the HTML is shown on the browser, but before SignalR is connected.

I've seen this in a button being visible in the browser, but before the onclick is registered - thus seeming to the user like the button is broken.

I think I've got round this by implementing an instance of CircuitHandler and using that to trigger a change on the page from loading spinner to actual page.

Firstly, do I have the correct understanding of the Blazor Server re-hydration?

Secondly, is there a better method that using the CircuitHandler?

Update: I can see that this re-hydration approach is set by the "ServerPrerendered"

<component type="typeof(App)" render-mode="ServerPrerendered" />

To avoid the de-hydrated html being sent in the first response, I can change to "Server".

That doesn't however display anything. Would be useful it that could show some sort of fallback (loading spinner) until the Server is ready.

1
Sounds like you may be looking for something like docs.microsoft.com/en-us/aspnet/core/blazor/… - Ben Sampica
Thank @BenSampica; that led me to this -> docs.microsoft.com/en-us/aspnet/core/blazor/components/… - Mark Taylor

1 Answers

0
votes

Thanks to the pointer provided by @BenSampica in the comments;

Documentation cab be found here -> https://docs.microsoft.com/en-us/aspnet/core/blazor/components/lifecycle?view=aspnetcore-3.1#detect-when-the-app-is-prerendering

Based on this I created a PreRenderLoadingMessage component:

@if (HasRendered)
{
    @ChildContent
}
else
{
    <div>Loading</div>
}
    
@code {
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    private bool HasRendered { get; set; }

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            HasRendered = true;
            StateHasChanged();
        }
    }
}

I then wrap my router with the component:

<PreRenderLoadingMessage>
    <Router AppAssembly="@typeof(Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
                @{ Is404 = true; }
            </LayoutView>
        </NotFound>
    </Router>
</PreRenderLoadingMessage>