Lifecycle hooks

A component instance has a lifecycle that starts when Blazor Server instantiates the component class and renders the component view along with its child views. The lifecycle continues with property change detection, as Blazor Server checks to see when the properties change and update the view. The lifecycle ends when Blazor Server destroys the component instance and removes its rendered template from the DOM.

Blazor Server is designed to let you interact with the initialization process, respond to updates when property changes, and clean up before GC collects instances.

You can download the example code used in this topic on GitHub.

Prerequisites

Before working with lifecycle hooks, you should have a basic understanding of the following:


Responding to lifecycle events

You can respond to events in the lifecycle of a component by overriding one or more of the lifecycle hook methods in the Microsoft.AspNetCore.Components.ComponentBase class. The hooks give you the opportunity to act on a component instance at the appropriate moment, as Blazor Server creates, updates, or destroys that instance.

You don't have to override all (or any) of the lifecycle hooks, just the ones you need. Here is an example of hooking a method to a component's lifecycle event.

@page "/hooking-method"

<h3>@Welcome</h3>

@code {
    private string Welcome = "";

    // interfere on init process of this component
    protected override void OnInitialized()
    {
        Welcome = "Welcome to Blazor School!";
    }
}

Lifecycle event sequence

After your application instantiates a component by calling its constructor (you won't see this constructor in high level component), Blazor Server calls the hook methods you have implemented at the appropriate point in the lifecycle of that instance.

Blazor Server executes hook methods in the following sequence. You can use them to perform the following kinds of operations.

Hook method Purpose Timing
OnInitialized() Initialize the component after Blazor Server renders the component.

Called at the beginning of the render process.

Server triggered.

OnInitializedAsync() Same as OnInitialized but for async operations.

Called after OnInitializedAsync().

Server triggered.

OnParametersSet() Respond to property changes.

Called after OnInitializedAsync() and whenever a property with attribute [Parameter] changed its value.

Server triggered.

OnParametersSetAsync() Same as OnParametersSet() but for async operations.

Called after OnParametersSet() is called.

Server triggered.

OnAfterRender(true) Render the component on the client side.

Called after OnParametersSetAsync(). You can understand it as Blazor Server has rendered the component on the server side.

Client triggered.

OnAfterRenderAsync(true) Same as OnAfterRender(true) but for async operations.

Called after OnAfterRender(true).

Client triggered.

OnAfterRender(false) Response to the StateHasChanged() method.

Called after whenever StateHasChanged() method is called.

Client triggered.

OnAfterRenderAsync(false) Same as OnAfterRender(false) but for async operations.

Called after whenever OnAfterRender(false) method is called.

Client triggered.

Dispose() To use this method, the component must have @implements IDisposable directive. This method responds to clean up the component.

Called after user navigates to another page or the component is being cleaned up.

Client triggered.

Lifecycle example

The example at the top of the page demonstrates the use of lifecycle hooks by calling them one by one and showing the log to the UI. You can look at HookMethodsCallingSequenceExample.razor component.

Blazor Server lifecycle example


Initializing a component

Use the OnInitialized() method to perform the following initialization tasks.

  • Perform fetching data. For example, getting data from the services.
  • Register for events. For example, registering for NavigationManager.LocationChanged.
  • Set the default value for the properties. If you don't set the default value for the property, then you must set it when you declare the property.

The OnInitialized() method cannot perform the following tasks.

  • Run JavaScript. You must not call any JavaScript at this stage because the component is still being rendered on the server side. There is no JavaScript on the server side.

Refer to the InitilizeAndDisposeComponentExample.razor component for a demonstration.

protected override void OnInitialized()
{
    Car = new() { Color = "Red" };
    Car.OnColorChanged += OnColorChangedHandler;
    Colors = new()
    {
        "Red",
        "Green",
        "Blue",
        "Violet"
    };
}

Cleaning up on instance destruction

To avoid memory leaks, you need to cleanup the resources before GC collects the component. You need to use @implement directive to implement IDisposable interface. Put cleanup code logic in Dispose(), the logic that must run before Blazor Server destroys the component.

This is the place to free resources that won't be garbage-collected automatically. You risk memory leaks if you neglect to do so.

  • Unsubscribe from events.
  • Stop working tasks.
  • Close opening stream.

Refer to the InitilizeAndDisposeComponentExample.razor component for a demonstration.

public void Dispose()
{
    Car.OnColorChanged -= OnColorChangedHandler;
}

Detecting parameter changes

Blazor Server calls the OnParametersSet() method of a component whenever it detects changes to the [Parameter] properties. This means that whenever the property is changed by the parent component, the OnParametersSet() method of the child parent will be fired. The CarDetail.razor demonstrated this by monitoring the OnParametersSet() hook.
protected override void OnParametersSet()
{
    Log += "CarDetail detected parameter changed <br>";
}

The example component, CarDetail.razor, has one input parameter Car.

[Parameter]
public Car Car { get; set; }

The host DetectParameterChangesExample.razor pass parameter as follows.

<CarDetail Car="Car"></CarDetail>

Here is an example in action as the user makes changes.

The log entries appear as the Car.Color property changes.

Note: The Car.Color is being manipulated by the host, not the CarDetail.razor itself.

Responding to property changes manually

In some scenarios, the child will modify a property and the parent component will not get notice that the property has changed. As Blazor Server traverses the DOM hierarchy during change detection, Blazor Server will not traverse back to the parent to increase performance. You need to use StateHasChanged(); to tell Blazor Server to render the caller component again.

Add an input to the CarDetail.razor to make the color editable from the car detail component.

<input @bind-value="@Car.Color" />

The @bind directive will create a binding between the value attribute of the input tag and the Car.Color property. The next step is to display the color in the parent component. Now, verify that the parent component is not updated when the child modifies the color.

Add a button to call StateHasChanged(); in the parent component.

<button @onclick="() => StateHasChanged()">Re-render</button>

Verify that the parent component is updated when click the button.

Responding to property changes automatically

The parent component now re-render whenever you press the Re-render button. In some cases, you want those changes to reflect automatically rather than pressing a button. You can archieve that with event keyword.
Navigate to Car.cs and convert the Color property to a full property.
private string _color;

public string Color
{
    get => _color;
    set => _color = value;
}

Declare a delegate OnColorChangedHandler. The delegate should take 2 parameters, the first one will be an object sender (sender of the event), the second one should be the data for the event, in this case, that is string color.

public delegate void OnColorChangedHandler(object sender, string color);

Declare an event for the delegate.

public event OnColorChangedHandler OnColorChanged;

Fire the event whenever the Color property changes.

public string Color
{
    get => _color;
    set
    {
        _color = value;
        OnColorChanged?.Invoke(this, value);
    }
}

Navigate to the parent component, use @implements directive to implement the IDisposable interface.

@implements IDisposable

Override the OnInitialized() method and add a Dispose() method in the @code{} section.

private void OnCarColorChanged(object sender, string color)
{
    StateHasChanged();
}

protected override void OnInitialized()
{
    Car.OnColorChanged += OnCarColorChanged;
}

public void Dispose()
{
    Car.OnColorChanged -= OnCarColorChanged;
}

The results are illuminating.

BLAZOR SCHOOL
Designed and built with care by our dedicated team, with contributions from a supportive community. We strive to provide the best learning experience for our users.
Docs licensed CC-BY-SA-4.0
Copyright © 2021-2025 Blazor School
An unhandled error has occurred. Reload 🗙