greenSacrifice
greenSacrifice

Reputation: 93

Blazor rendering content twice

I've tried different ways to prevent this from happening.

After changing to render-mode="Server" I was able to prevent rendering twice on the first load.

But now when I refresh the page it still doubles the amount of elements.

Here is what I've got

<div id="component-wrapper" class="row">
    @if (Items != null)
    {
        @foreach (var item in Items )
        {
            <ItemComponent Item="@item" />
        }
    }
</div>

@code {

    [Inject]
    private IItemService ItemService { get; set; }
    List<ItemViewModel> Items { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Items = await ItemService.GetItemsAsync();
        base.OnInitialized();
    }
}

I've read over the Stateful reconnection after prerendering section and it doesn't seem to work for me.

Upvotes: 6

Views: 11127

Answers (5)

Kevon
Kevon

Reputation: 1297

For anyone else who is hitting this "loading twice" with .Net 8 and "AutoRender" mode. I found this post to be valuable:

https://jonhilton.net/persist-state-between-renders-net8/#:~:text=Chances%20are%20it's%20down%20to,show%20something%20nice%20and%20quickly.

By default in .NET 8 your interactive components are rendered twice:

Once on the server (prerendering), where HTML is returned so the browser can show something nice and quickly.

Then your component will be rendered again using your preferred interactive render mode (server or WASM).

The problem is, if you’re fetching data in your component, it’s going to be fetched for both renders.

You can often see this in the UI, with a visible flash as the prerendered content is replaced with the “new data” when your component is rendered for a second time.

So what to do about it? Turns out there are two main options at your disposal:

Disable prerendering Persist state between the first and second renders

Upvotes: 2

Nick Kovalsky
Nick Kovalsky

Reputation: 6452

In case of Blazor Server, modifying _Host.cshtml solved this for me:

before

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

after

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

Upvotes: 7

Pablo Fuenzalida
Pablo Fuenzalida

Reputation: 129

For me it was that this script was duplicated on _Hosts.cshtml

<script src="_framework/blazor.server.js"></script>

After deleting one of them problem was solved.

Upvotes: 6

Remi THOMAS
Remi THOMAS

Reputation: 910

Don't override OnInitialized Use OnAfterRender or OnAfterRenderAsync

protected override async Task OnAfterRenderAsync(bool firstRender)

With firstRender you get the info. You can also use our own mecanism to avoid loading your context more than one time.

If needed call StateHasChanged to update the DOM.

https://learn.microsoft.com/en-us/aspnet/core/blazor/components/lifecycle?view=aspnetcore-5.0

EDIT

The easiest way to solve this problem is to use browser localstorage. You can save user id and then get it back in case of a refresh. If a user press F5 to refresh the page, blazor will create a new circuit and there is no easy solution on the server side.

Upvotes: -2

greenSacrifice
greenSacrifice

Reputation: 93

Turns out in a further down stream service where I've added to the list, I wasn't creating an empty list to begin with.

Thanks for assisting.

Upvotes: 0

Related Questions