Component Lifecycle in Blazor

In this post, we will see how the lifecycle of Blazor components works and the methods we can use to interact with the component lifecycle. 

 

1 - Dependency Injection with Blazor

For this post, it's important that you have a clear understanding of the concept of dependency injection. The logic is the same as in C#. 

Here are the links you need to understand before continuing with this post

 

There is only one thing that differs between Blazor and "regular" C#, and that's that in C# we usually inject dependencies in the constructor of our class. 

But in Blazor, as we saw in the post about Blazor components, we do not have a constructor, so we must inject it using @inject within our .razor file or [Inject] in our partial class.

 

In our case we inject IHttpClientFactory  and it would look like one of the following forms:

//PerfilPersonal.razor
@inject IHttpClientFactory ClientFactory

//PerfilPersonal.razor.cs
[Inject]
private IHttpClientFactory ClientFactory { get; set; }

 

 

2 - HTTP Calls with Blazor

To make HTTP calls with Blazor, we'll follow the same logic as in C#. For this purpose, we use IHttpClientFactory. If you're not familiar with HTTP calls, I recommend you read the following post:

The only difference you might encounter is that if you are using .NET5 you can import the package using System.Net.Http.Json and automatically deserialize your response. 

var client = ClientFactory.CreateClient("BackendApi");
return await client.GetFromJsonAsync<ResultDto<PersonalProfileDto>>($"api/perfilpersonal/{profileCode}");

 

3 - Component Lifecycle

When we talk about Blazor, we're talking about components, small pieces of code.

Before moving on, note that these methods can be either synchronous or asynchronous. In this case, since we are calling an external service, they will be asynchronous. 

For this example we will query our personal profile in the back-end, which will be part of the URL. To access it, simply use https://localhost:44363/perfil/{nombre}

 

But how do we receive these values?

First of all, remember from the previous post that with the @page directive, we can pass a parameter from the URL.

We need to capture this parameter and send it to our component where we display the information, as it is in the component where we will make the HTTP call. 

@page "/perfil/{Name}"
@using WebPersonal.FrontEnd.WebApp.Componentes

<PerfilPersonal Profile="@Name"></PerfilPersonal>

@code{
    [Parameter]
    public string Name { get; set; }
}

Now we need to know how to handle this parameter to ensure our page works as expected

 

3.1 - SetParameterAsync

The SetParameterAsync method is the first to run when a component is created. All parameters sent to the component are stored in the ParameterView type, so if we want to perform any action before the parameters are assigned, we can do it here.

public override Task SetParametersAsync(ParameterView parameters)
{
    return base.SetParametersAsync(parameters);
}

 

3.2 - OnInitialized and OnInitializedAsync

These methods are executed right when the component is initialized. 

protected override void OnInitialized()
{
    base.OnInitialized();
}
protected override Task OnInitializedAsync()
{
    return base.OnInitializedAsync();
}

It is important to note that these methods only execute once per component. 

 

3.3. - OnParameterSet and OnParameterSetAsync

These methods execute when, after receiving parameters, the values are assigned to properties, and they execute each time the parameters are updated. 

protected override void OnParametersSet()
{
    base.OnParametersSet();
}
protected override Task OnParametersSetAsync()
{
    return base.OnParametersSetAsync();
}

 

3.4 - OnAfterRender and OnAfterRenderAsync

When the component finishes rendering, these methods are executed. 

protected override void OnAfterRender(bool firstRender)
{
    base.OnAfterRender(firstRender);
}
protected override Task OnAfterRenderAsync(bool firstRender)
{
    return base.OnAfterRenderAsync(firstRender);
}

 

3.5 - StateHasChanged

This is the method you should call when you change something in your component so it re-renders. For example, if you want to show or hide a modal, you have to re-render the component.

 

3.6 - ShouldRender

With this method, you can block the user interface from refreshing since it is called every time the component renders. That said, even if you return `false`, if it is the first render, the component will still render.

 

3.7 - Dispose

As an additional note, you can implement IDisposable in your class, and therefore you must implement the Dispose method.

If you don't know how to implement dispose, check the following link:

 

 

4 - Example of a Component Lifecycle in Blazor

For this example, let's look at something very common: reading from one profile to another. It would be similar to switching blog posts.

For this example, we'll use the project we've been using so far, which is available in the GitHub link in this same post.  

 

Therefore, we will make a call to https://localhost:44363/perfil/{nombre}

The first thing we need to make clear is that the component will start assigning values and rendering when `SetParameterAsync` finishes. This means that if we need to make external service calls (for example, to read the complete profile), we can't access it until that call is finished. 

Speaking in code, if we have something like the following:

<div>
    <div class="row">
        <div class="col-sm-12 text-center">@PersonalProfile.FirstName @PersonalProfile.LastName</div>
    </div>
</div>

We assume it will print the first and last name, but this is not the case because PersonalProfile is null, which will therefore throw an exception.

 

We must wait until PersonalProfile has a value to display the information.

@if (PersonalProfile != null)
{
    <div>
        <div class="row">
            <div class="col-sm-12 text-center">@PersonalProfile.FirstName @PersonalProfile.LastName</div>
        </div>
    </div>
}

 

Note: you can also use the "coalesce value" @(PersonalProfile?.FirstName ?? "").

 

4.1 - Where to Call an External Service from Blazor

It is now clear that before displaying anything, you need to assign a value to the PersonalProfile property. Where should you do it?

The first thing to come to mind is to do it within OnInitializedAsync since it is the method that runs when we initialize the component.

protected override async Task OnInitializedAsync()
{
    var result = await GetPersonalProfile(Profile);
    if (!result.Errors.Any())
        PersonalProfile = result.Value;
    else
        Erros = result.Errors;
}

private async Task<ResultDto<PersonalProfileDto>> GetPersonalProfile(string profileCode)
{
    var client = ClientFactory.CreateClient("BackendApi");
    return await client.GetFromJsonAsync<ResultDto<PersonalProfileDto>>($"api/perfilpersonal/{profileCode}", new JsonSerializerOptions
    {
        PropertyNameCaseInsensitive = true
    });
}

And technically, it works – or so it seems. 

Let's check how this is not the right solution. 

If we add a second profile, put it as a link at the end of the page, and click this very link, we'll notice that the URL changes but the content remains the same. 

<a href="/perfil/netmentor"> Link to the second profile</a>

blazor lifecycle 1

This occurs because OnInitializedAsync only executes once per component and, for our routing, both /perfil/ivanabad and /perfil/netmentor are the same component since both match /perfil/{Nombre}.

 

For the information to update, we must make the call to our `Back-End` within OnParameterSet or OnParameterSetAsync. This is because, as mentioned, the component does not change, only the parameter changes.

 

To implement the lifecycle correctly, what we are going to do is create a private property which will contain the value of our  Profile parameter, but we won't receive it directly. Instead, we will assign it from the received parameter. We do this to check if the parameter has changed or is the same, and if it has changed, reload it.

 

See the implementation in the following code snippet:

public partial class PerfilPersonal
{
    [Inject]
    private IHttpClientFactory ClientFactory { get; set; }
    [Parameter]
    public string Profile { get; set; }
    private string _profileValue { get; set; } //Private property to store current value
    public PersonalProfileDto PersonalProfile { get; set; }
    public List<ErrorDto> Erros { get; set; }

    protected override async Task OnParametersSetAsync()
    {
        if (_profileValue != Profile) //Compare the value, and if it is different, fetch new info
        {
            await CalculateProfile();
        }

        await base.OnParametersSetAsync();
    }

    private async Task CalculateProfile()
    {
        _profileValue = Profile; //Assign value
        var result = await GetPersonalProfile(Profile);
        if (!result.Errors.Any())
            PersonalProfile = result.Value;
        else
            Erros = result.Errors;
    }

    private async Task<ResultDto<PersonalProfileDto>> GetPersonalProfile(string profileCode)
    {
        var client = ClientFactory.CreateClient("BackendApi");
        return await client.GetFromJsonAsync<ResultDto<PersonalProfileDto>>($"api/perfilpersonal/{profileCode}", new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        });
    }
}

You should use the same implementation in all components that have a parameter that can change.

blazor component lifecycle

 

Conclusion

  • In this post, we have seen that dependency injection in Blazor is a bit different than dependency injection in our C# classes.
  • We have seen that HttpClient works the same in Blazor as it does in C#.
  • We have seen how the component lifecycle in Blazor works and an example of how to implement a component's lifecycle.

 

This post was translated from Spanish. You can see the original one here.
If there is any problem you can add a comment bellow or contact me in the website's contact form

Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2025 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café