Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use OnAfterRenderAsync instead of OnInitializedAsync?

Tags:

c#

blazor

In a Blazor server component, I use OnInitializedAsync() to connect an event from an injected service:

protected override async Task OnInitializedAsync()
{
    _fooRepository.SomethingChanged += OnSomethingChanged;
    await Refresh();
}

public void Dispose()
{
    _fooRepository.SomethingChanged -= OnSomethingChanged;
}

private async Task Refresh()
{
    this.FooData = await LoadDataFromRepository();
}

Unfortunately, according to the documentation, the OnInitializedAsync method may be called twice, depending on the render mode.

I found some examples that recommend using OnAfterRenderAsync for the initialization logic instead:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        _fooRepository.SomethingChanged += OnSomethingChanged;
        await Refresh();
    }
}

[... Dispose and Refresh as above... ]

Are there disadvantages when using OnAfterRenderAsync instead of OnInitializedAsync? It seems to me that I should abandon OnInitializedAsync and default to OnAfterRenderAsync instead.

like image 635
pschill Avatar asked Dec 07 '25 10:12

pschill


1 Answers

Note. This answer was updated on 5-Sep-2023 by the author to incorporate comments on OnAfterRender with the advice in point 3 revised, and again on 15 July 2024 to reflect Net 8 Blazor interactivity.

It's important to understand what's going on with pre-rendering.

The page is rendered twice:

  1. Once by the server to build a static version of the page. This loads and then disposes of all the components correctly.
  2. A second time by the Blazor Hub session when a SignalR session is established by blazor.server.js running in the browser session.

Points:

  1. These two loads are totally separate, and there's no leaks with registering/unregistering event handlers.
  2. This only happens when the application first loads. After than it's one load per page.
  3. OnInitialized{Async} is the natural place for registering event handlers. You should not implement them in OnAfterRender{Async}. Why not? You should register them within the OnInitialized{Async}/OnParametersSet{Async} process, not in a UI event process [see the detailed information below].

If you're worried about load time with rendering a page twice, keep the landing page short and sweet.

A final comment. In your code, do the initial load of your data and then register for the SomethingChanged event.

On OnAfterRender

OnAfterRender{Async} is part of the DOM event process, not the OnInitialized{Async}/OnParametersSet{Async} process. It's driven by the Renderer receiving a DOM updated event from the DOM. While OnInitialized{Async}/OnParametersSet{Async} may trigger a render event [through calling StateHasChanged, and thus eventually a OnAfterRender{Async} event once that render has occured], the two are not directly coupled. OnAfterRender{Async} is part of another process, so there is no guarantee when it's run.

In general you should only use OnAfterRender{Async} to do JSInterop stuff. Doing anything in OnAfterRender{Async} that mutates the state of the component [and inevitably necessitates another call the StateHasChanged and another render and another OnAfterRender{Async}] is illogical. All state mutation should happen in OnInitialized{Async}/OnParametersSet{Async}.

Net 8 Interactivity

When a component page SSR renders on the server in Net8 OnAfterRender{Async} isn't called. It therefore seems like a good place to place code that you only want to run when a component is interactively rendered. DON'T: the reasons given above still apply.

Detect pre-rendering in OnInitialized{Async} and code accordingly. There's a Repo here that demonstrates how to detect pre-render. Note that Pre-Render detection is probably going to built in to ComponentBase in Net9.

You can also implement a pre-render splash screen see this question/answer - Blazor .Net 8 splash screen

like image 94
MrC aka Shaun Curtis Avatar answered Dec 11 '25 06:12

MrC aka Shaun Curtis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!