Blazor Architecture
Understanding what happens between your C# code and the browser explains most Blazor behaviour — and most Blazor bugs.
On this page · 5 min · Beginner
On this page
- Learning objectives
- Explanation
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Beginner
- Updated
- Oct 29, 2026
Related tutorials
Interview questions
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#
@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");
}
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#
- OnInitialized runs once when the component is created.
- OnParametersSet runs after parameters are applied.
- Each click changes state, re-renders, and only the button text is updated in the DOM.
- 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#
The DOM is not ready yet, and during prerendering there is no browser. Use OnAfterRenderAsync(firstRender).
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
OnInitializedAsync — it runs once when the component starts and supports await.
Mini quiz#
Over what does Interactive Server send UI updates?
Want more? Practise all Blazor MCQs · Blazor interview questions
My notes#
Saved in this browser.