100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
C#

Component Lifecycle Methods

Walk through Blazor's component lifecycle — from OnInitialized through OnParametersSet, OnAfterRender, and IDisposable — to know exactly when to run setup and cleanup logic.

Components & Data BindingIntermediate9 min readJul 10, 2026
Analogies

The Initialization Sequence

When a Blazor component is first created, it runs through a fixed sequence: SetParametersAsync assigns incoming parameter values, then OnInitialized/OnInitializedAsync runs exactly once for the component's lifetime (ideal for loading initial data), followed by OnParametersSet/OnParametersSetAsync, which runs after OnInitialized and again every time the parent supplies new parameter values, making it the right place to react to parameter changes rather than OnInitialized.

🏏

Cricket analogy: A new player's international debut follows a fixed sequence — selection announcement, then the toss, then walking out to bat — that happens once for the debut, while later a returning veteran skips straight to the toss stage each subsequent match, similar to OnInitialized firing once versus OnParametersSet firing on every parameter change.

Rendering Hooks: ShouldRender and OnAfterRender

OnAfterRender/OnAfterRenderAsync fires after the component has rendered its markup to the DOM, receiving a firstRender boolean parameter that's true only on the very first render, making it the correct place to call JavaScript interop that needs the DOM element to already exist, such as initializing a third-party chart library; ShouldRender can be overridden to return false and skip an unnecessary re-render entirely, which is a targeted performance optimization for components that render expensive markup but rarely need to update.

🏏

Cricket analogy: Ground staff only run their full pitch-covering tarp inspection once, right after the ground is first prepared for the season, similar to how OnAfterRender's firstRender flag is true only on the component's very first render.

Cleaning Up with IDisposable

A component that subscribes to an event, starts a Timer, or holds an injected service reference that itself needs disposal should implement IDisposable (or IAsyncDisposable for async cleanup) and unsubscribe or dispose resources in the Dispose method; failing to do so is a common source of memory leaks in Blazor Server apps in particular, since the circuit and its component tree can persist across many renders, and an undisposed timer or event handler continues firing and holding references even after the component is logically gone.

🏏

Cricket analogy: A commentator who's finished their assigned overs must formally hand back the microphone and leave the commentary box, or they keep occupying a slot needed for the next shift, similar to a component needing to unsubscribe and dispose resources in IDisposable.Dispose to free them properly.

razor
@implements IDisposable
@inject IStockPriceService StockPrices
@inject IJSRuntime JS

<h3>@Ticker: @price.ToString("C")</h3>
<canvas id="chart-@Ticker"></canvas>

@code {
    [Parameter] public string Ticker { get; set; } = string.Empty;

    private decimal price;

    protected override async Task OnInitializedAsync()
    {
        // Runs once: initial data load
        price = await StockPrices.GetPriceAsync(Ticker);
        StockPrices.PriceChanged += HandlePriceChanged;
    }

    protected override void OnParametersSet()
    {
        // Runs after OnInitialized, and again whenever Ticker changes
        Console.WriteLine($"Now tracking {Ticker}");
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            // DOM element with id chart-{Ticker} now exists
            await JS.InvokeVoidAsync("chartInterop.init", $"chart-{Ticker}");
        }
    }

    private void HandlePriceChanged(object? sender, decimal newPrice)
    {
        price = newPrice;
        InvokeAsync(StateHasChanged);
    }

    public void Dispose()
    {
        StockPrices.PriceChanged -= HandlePriceChanged;
    }
}

The full sync order on first render is: SetParametersAsync -> OnInitialized/OnInitializedAsync -> OnParametersSet/OnParametersSetAsync -> render -> OnAfterRender/OnAfterRenderAsync. On subsequent updates triggered by new parameters, only SetParametersAsync -> OnParametersSet/OnParametersSetAsync -> render -> OnAfterRender run again; OnInitialized never runs a second time.

Calling StateHasChanged() unconditionally inside OnAfterRender (especially without checking firstRender) can trigger an infinite render loop, since each re-render fires OnAfterRender again. Only call StateHasChanged from OnAfterRender when guarded by a condition (like firstRender or a one-time initialization flag) that eventually stops triggering it.

  • SetParametersAsync assigns incoming parameters before any other lifecycle method runs.
  • OnInitialized/OnInitializedAsync runs exactly once per component instance, ideal for initial data loading.
  • OnParametersSet/OnParametersSetAsync runs after OnInitialized and again on every subsequent parameter update.
  • OnAfterRender/OnAfterRenderAsync runs after the DOM is updated, with firstRender=true only on the first call.
  • ShouldRender can be overridden to return false and skip unnecessary re-renders for performance.
  • Components holding subscriptions, timers, or disposable injected services should implement IDisposable.
  • Undisposed resources are a common cause of memory leaks, especially in long-lived Blazor Server circuits.

Practice what you learned

Was this page helpful?

Topics covered

#BlazorStudyNotes#MicrosoftTechnologies#ComponentLifecycleMethods#Component#Lifecycle#Methods#Initialization#Functions#StudyNotes#SkillVeris