Blazor · Foundations

Blazor Architecture

Understanding what happens between your C# code and the browser explains most Blazor behaviour — and most Blazor bugs.

Beginner 5 min Lesson 2 of 31Examples target .NET 9 Blazor Web App.
Before you start:Introduction to Blazor
0/31 in Blazor
On this page · 5 min · Beginner

Learning objectives#

  • Describe the component tree and render tree
  • Explain how UI updates are diffed
  • Compare server, WebAssembly and static hosting
  • Know the component lifecycle methods

Explanation#

A Blazor app is a tree of components. Rendering a component produces a render tree — an in-memory description of its markup.

When state changes, Blazor renders again, compares (diffs) the new render tree with the previous one and sends only the changes to the DOM.

Where that happens depends on the render mode: on the server with diffs sent over a SignalR “circuit”, in the browser on the .NET WebAssembly runtime, or once per request as plain HTML (static SSR).

Lifecycle: SetParametersAsync → OnInitialized{Async} (once) → OnParametersSet{Async} → render → OnAfterRender{Async}(firstRender). Dispose with IDisposable/IAsyncDisposable.

Code example: Watching the lifecycle#

Razor / MarkupComponents/Pages/Lifecycle.razor Illustrative
@page "/lifecycle"
@rendermode InteractiveServer
@implements IDisposable


<button @onclick="() => count++">Clicked @count times</button>


@code {
    private int count;


    protected override void OnInitialized() => Console.WriteLine("OnInitialized");
    protected override void OnParametersSet() => Console.WriteLine("OnParametersSet");
    protected override void OnAfterRender(bool firstRender) =>
        Console.WriteLine(
quot;OnAfterRender (firstRender: {firstRender})");
public void Dispose() => Console.WriteLine("Dispose"); }
Expected output
OnInitialized
OnParametersSet
OnAfterRender (firstRender: True)
OnAfterRender (firstRender: False)   ← after each click
Dispose                               ← when you navigate away

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. OnInitialized runs once when the component is created.
  2. OnParametersSet runs after parameters are applied.
  3. Each click changes state, re-renders, and only the button text is updated in the DOM.
  4. Dispose runs when the component leaves the page — the place to unsubscribe from events.

Real-world use case#

A dashboard subscribes to a notification service in OnInitialized and unsubscribes in Dispose, avoiding memory leaks on a long-running server circuit.

Common mistakes#

Calling JavaScript in OnInitialized

The DOM is not ready yet, and during prerendering there is no browser. Use OnAfterRenderAsync(firstRender).

Forgetting to dispose subscriptions

Event handlers keep components alive and cause leaks, especially in Interactive Server circuits.

Best practices#

  • Load data in OnInitializedAsync
  • Do DOM/JS work in OnAfterRenderAsync(firstRender)
  • Implement IDisposable for subscriptions and timers
  • Keep render logic cheap

Remember this#

Render tree → diff → minimal DOM changes.

Initialized once; ParametersSet on every parameter change.

JS interop after first render, never before.

Practice exercise#

Your task: Which lifecycle method should load a product list from an API?

Show solution
Text Illustrative
OnInitializedAsync — it runs once when the component starts and supports await.

Mini quiz#

Blazor Architecture quizMultiple choice Question 1 of 1

Over what does Interactive Server send UI updates?

Score so far: 0/0

Want more? Practise all Blazor MCQs · Blazor interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.