blazor-ciclo-de-vida-componentes

Lifecycle in Blazor: Methods and Execution Order

  • 5 min

The lifecycle of a Blazor component is the sequence of methods that execute during its creation, update, rendering, and disposal.

As developers, we need to intervene at precise moments in this existence:

  • When do I load data from the database?
  • When do I recalculate variables if the parent changes a parameter?
  • When can I call a JavaScript library to render a chart?

To intervene at those moments, Blazor provides virtual methods that we can override.

MethodWhen it runsMain purpose
OnInitializedWhen initializing the instanceLoad initial data that does not depend on parameter changes.
OnParametersSetOnce + on every parameter changeRecalculate data based on parameters (ProductId, SearchTerm).
OnAfterRenderAfter each interactive renderCall JavaScript, focus controls, or scroll the page.
DisposeWhen the component is removedCancel tasks and clean up events or timers.

The general flow

Before going into detail, let’s look at the standard execution sequence when a component renders:

Instantiation: The class is created (Constructor).

SetParametersAsync: Parameters are injected.

OnInitialized{Async}: The component is initialized.

OnParametersSetAsync: The component receives/updates data.

OnAfterRender{Async}: The interactive UI has already been updated.

Let’s analyze the three fundamental pillars you will use in 99% of your components.


OnInitialized and OnInitializedAsync

This method executes when initializing an instance, after it has received its initial parameters. In an application with prerendering, initialization may run twice: once to generate HTML on the server and once when interactive rendering begins.

It is the equivalent of the constructor, but with a crucial difference: in the constructor, [Parameter] and dependency injections (@inject) are not ready yet. In OnInitialized, they are.

What do we use it for? Mainly to load initial data from a database or API.

@inject IUserService UserService

<h3>Profile of @User?.Name</h3>

@code {
    private UserDto User;

    protected override async Task OnInitializedAsync()
    {
        // Simulate a database call
        // We do this here and not in the constructor
        User = await UserService.GetUserByIdAsync(1);
    }
}
Copied!

Use the asynchronous variant (OnInitializedAsync) when awaiting an API, database, or other I/O operation. Avoid blocking the component’s execution context with slow synchronous work.


OnParametersSet and OnParametersSetAsync

This is where mistakes are easily made.

This method executes:

  1. Immediately after OnInitialized.
  2. When the parent supplies parameters again. For complex types, Blazor may treat them as modified even if the reference appears the same.

What do we use it for? To react to changes. Imagine a component that shows product details based on an Id provided by the parent.

  • If you load the product in OnInitialized, it will only work the first time.
  • If the user switches products without leaving the page, OnInitialized will not run again, but OnParametersSet will.
<h3>Product Detail: @Product?.Name</h3>

@code {
    [Parameter]
    public int ProductId { get; set; }

    private ProductDto Product;

    // Runs every time ProductId changes
    protected override async Task OnParametersSetAsync()
    {
        Product = await ProductService.GetByIdAsync(ProductId);
    }
}
Copied!
  • If data loading depends only on component creation, use OnInitialized.
  • If data loading depends on a [Parameter] that can change, use OnParametersSet.

OnAfterRender and OnAfterRenderAsync

This method executes after an interactive render, when the changes have already been applied to the DOM and references to elements and components are available. It does not run during prerendering or static SSR.

This method receives a boolean firstRender:

  • true: It is the first time the component is rendered.
  • false: It is a subsequent update.

What do we use it for? Mainly for initialization that requires already rendered content, such as interacting with JavaScript via JS Interop.

Before this point, HTML elements do not exist in the browser. If you try to call a JS function to render a Google Maps map in OnInitialized, it will fail because the <div id="map"> does not exist yet.

@inject IJSRuntime JS

<div id="my-chart"></div>

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        // Only initialize JS libraries the first time
        if (firstRender)
        {
            await JS.InvokeVoidAsync("startChart", "my-chart");
        }
    }
}
Copied!

Beware of repeated renders: If you call StateHasChanged without a condition inside OnAfterRender, you schedule another render and can create a loop. OnAfterRenderAsync does not automatically re-render when its Task finishes, precisely to avoid this issue.

Releasing resources with Dispose

Although not an “active” lifecycle method, it is important for the “death” phase. If your component subscribes to events (from a service, for example) or creates timers, you must clean them up when the user leaves the screen.

To do this, the component must implement IDisposable or IAsyncDisposable.

@implements IDisposable

@code {
    protected override void OnInitialized()
    {
        MyService.OnChange += HandleChange;
    }

    public void Dispose() // Called when Blazor removes the component
    {
        // IMPORTANT: Unsubscribe to prevent memory leaks
        MyService.OnChange -= HandleChange;
    }
}
Copied!