David Thielen
David Thielen

Reputation: 32966

Blazor InteractiveServer and pre-rendering - when is OnInitializedAsync() called?

I am upgrading my app from Blazor Ver 6/7 Server side to Ver 8 InteractiveServer. I want pre-rendering which will render the page scaffold/skeleton first, then we take the time to read from the DB to populate the page with data.

To summarize, the way to have the entire app, all components (unless explicitly specified differently) to be InteractiveServer with pre-rendering on is:

Program.cs:

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();
// other stuff
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

And in App.razor:

    <HeadOutlet @rendermode="InteractiveServer" />
</head>
<body>
    <Routes @rendermode="InteractiveServer" />
    <script src="_framework/blazor.web.js"></script>
</body>

So here's my question. In my testing OnInitializedAsync() is called exactly once. After the scaffold/skeleton is rendered. If I put a Task.Delay() in OnInitializedAsync() then it goes:

  1. enter OnInitializedAsync
  2. Task.Delay()
  3. page skeleton displayed
  4. OnAfterRenderAsync
  5. OnInitializedAsync completes

This is all great. But there were issues around OnInitializedAsync() being called twice. Is being called twice only for SSR + Streaming? And as such, not an issue here?

And... I went back and looked at an old question of mine. In one of the early release candidates for Ver 8, for InteractiveServer mode, was it calling OnInitializedAsync() twice?

Upvotes: 0

Views: 566

Answers (1)

MrC aka Shaun Curtis
MrC aka Shaun Curtis

Reputation: 30177

All correct except:

  1. OnAfterRenderAsync

You're falling back into thinking of OnAfterRenderAsync as part of the lifecycle methods, rather than a UI Event.

This is a serious oversimplification, but consider the Blazor Synchronisation Context has two queues.

  1. The Send/Post queue where all Rendering [RenderFramgents] and Continuations are posted.
  2. An event queue were UI events are posted.

The synchronisation context prioritises the post queue over the UI event queue, which dictates when OnAfterRenderAsync runs.

If the post queue is clear [all work queued has completed] when the renderer queues a UI event, it's run immediately. However, if the post queue is busy and the continuation from Task.Delay is already posted [or posted while the queue is busy], OnAfterRenderAsync is not run until the post queue clears i.e. last.

Also note that if OnInitializedAsync yields, the component is rendered twice, and thus OnAfterRenderAsync will be run twice.

Upvotes: 0

Related Questions