Better Programming

Advice for programmers.

Blazor Life Cycle Events: Oversimplified

Rikam Palkar - Microsoft MVP
Better Programming
Published in
7 min readOct 12, 2022

--

Photo by Campaign Creators on Unsplash

Right from the moment the razor component comes alive, there are a series of methods that get called based on different states of the component. We should have a clear understanding of the flow of the control.

Today, I will teach you different life cycle methods of the razor component and when to call what. There are eight methods that come under this component life cycle.

Let’s start from the beginning by getting to know the architecture of the Blazor page, then learn various synchronous and asynchronous methods.

The following image shows different parts of the razor page:

Image 1: Sample Blazor component

In some scenarios, we want C# code to run first, and then UI to render. So the objects we are binding in the UI will have data. For example, List will get filled up with four items first, then the UI will know there are four rows in DataGrid. On the flip side, sometimes we want UI to render first and then C# code to run.

How to achieve all this? That’s what we are going to learn today. Let’s begin with the first state.

1. OnInitialized and OnInitializedAsync

These two methods are called before the component is rendered, First, we make service calls to fill all the objects which are then bound on the screen.

Let’s see this in action.

Create a Parent and a Child component, and add the instance of the Child component inside Parent. Refer to the image below:

Image 2: Create Parent and Child Component

Parent look something like this:

Listing 1: Parent.razor

Child component: We are going to use List<string> to keep the track of the number of events added.

Listing 2: Child.razor

If you run this app, you’ll notice this. When the app starts, these two methods are called first, in the order shown below:

oninitialized, oninitializedasync
Image 3: Output of listing 1 and 2

2. OnParametersSet and OnParametersSetAsync

These methods are invoked by the following two triggers:

  1. Every time new parameters are received from the parent these methods are called.
  2. Also when the component is loaded for the first time these methods are called right after OnInitialized() and OnInitializedAsync().

To see this in action, we need to make a few changes in our components.

The Parent component will now send a parameter named “counter” to the child component and also be responsible to update the value of this counter. We can achieve this with a button click.

Listing 3: Parent.razor

Now for the child component. It will receive the parameter from the Parent and show the value of that parameter in UI. This is where we will expose our two methods, OnParametersSet() and OnParametersSetAsync().

Listing 4: Child.razor

Now, observe the series of images below and notice the flow.

Scenario 1: The application runs for the first time, and the order of execution is as follows: OnInitialized() => OnInitializedAsync() => OnParametersSet() => OnParametersSetAsync().

Image 4: Component Initialized

Scenario 2: The button on the Parent component is clicked once, which sends an updated “counter-parameter” to the child component, you can see how OnParametersSet() and OnParametersSetAsync() gets called again.

Image 5: New parameter is sent from parent to child component

Scenario 3: The button is clicked once again, and the same pattern is observed in the child component.

Image 6: New parameter is sent from parent to child component

3. OnAfterRender and OnAfterRenderAsync

These methods are called after the component is rendered. More on this later!

If you look at the syntax shown in the following snippet, you’d see these methods have one boolean parameter firstRender, the value of firstRender is true if the component is rendered for the first time. If not, it is false.

Listing 5: OnAfterRender and OnAfterRenderAsync

In the following couple of images let me show you the execution flow of these two methods. Image 7 shows the flow when the component is rendered for the first time. It calls both methods OnAfterRender() and OnAfterRenderAsync() twice.

For the first time, the boolean value of firstRender is true and then these methods get called again. This time, the value of firstRender is false.

Image 7: Component rendered for the first time

What happens if the child component receives a new update from the parent and renders itself again? The same pattern from image 7 is followed except there are changes in the OnInitialized() and OnInitializedAsync() methods.

Image 8: Component is rerendered with new values

Now, let’s dig deep to understand what we actually need these methods for.

In order to answer this question, I have to make a few changes to our code. I am going to move the “counter-button” to the child component with its OnclickHandler(), then override OnAfterRender(). Also, I am logging the “value of the counter” to the console-tab to cross-verify the current value of the “counter. Here’s what the child component will look like after these changes:

Listing 6: Child.razor

Let’s have a look at the parent component after some code cleanup.

Listing 7: Parent.razor

Run the app, and you’ll see how OnAfterRender actually works.

In the following figure, I am running the application for the first time. As you can see in the Console tab, the value of the counter has been increased by the OnAfterRender() method, but the UI is not showing the updated value. To put it in simple words, OnAfterRender() executes code after the UI has been rendered.

Image 9: Value in console is updated where the value on UI is not

Now, what would happen if I click the button? It will render the component again.

First, IncreaseCounter() will be called. This increases the value of the counter to 2, then UI is rendered with value 2, then OnAfterRender is called, but the UI is not rendered again.

Image 10: OnAfterRender() method increasing the value but UI is ignoring that update

Just to follow through, I will click on the button one more time.

Image 11: OnAfterRender() method increasing the value but UI is ignoring that update

4. StateHasChanged

This life cycle method notifies the UI about the new value and this triggers the rerendering of the component.

  • Use: If you are calling async services and want the UI to be rendered again based on new values, you can use this method. Simply put, it notifies the component that the State has changed so it will load the component again with a new value.

Let’s first learn why we need StateHasChanged().

To demonstrate this, we need something that gets triggered by itself. For that, we can simply use timer. We will run the timer until the value of the counter reaches 5. With each second, we will increase the value of the counter by 1.

Scenario 1: When we don’t use StateHasChanged()

  • Observe how UI threads stay unresponsive to any changes made to counter variables by timer.

Note: Make the following changes in the child component.

Listing 8: Child.razor

Let’s fire the application and observe the value of the “counter” in the console vs. the value of the “counter” on UI. UI is not rerendering.

Gif 1: UI is independent of StateHasChanged

Scenario 2: When we use StateHasChanged()

Now just call StateHasChanged() in TimeCallBack(). Refer to line number 6 from the following snippet:

Listing 8: Child.razor

Now see the difference! The UI is rerendering and showing the counter’s increment.

Gif 2: UI is re-rendering because of StateHasChanged

5. ShouldRender

If it returns true, it will forcefully refresh the UI. If not, the updated state of the object will stay in memory but the UI thread will have no idea what the new value is.

Scenario 1: When we return false from ShouldRender()

  • Let’s use the same example. This time, override ShouldRender() in the child component as follows. You’ll see that it returns false from the method.
Listing 9: Child.razor

If I run this app, then the ShouldRender method will get called, but it will block UI from being rendered because we are returning false from the method. Observe how the values in the console are changing, but the UI is unaffected by those changes.

Gif 3: ShouldRender returning false

Scenario 2: When we return true from ShouldRender()

Listing 10: Child.razor

The same execution flow will follow, but this time the UI will render updated values.

Gif 4: ShouldRender returning true

Conclusion

All right, this was a long article, but I am sure it was helpful. Now we know what different life cycle methods are in Blazor and how they define the state of the component. Once you start designing components, you’ll get a clearer understanding of which lifecycle method to use and when.

Here are a few topics I’ve covered. You can merge to Blazing Blazor’s repository, and learn the following topics.

  1. Event Callback
  2. RenderFragment
  3. CSS Custom Properties
  4. AttributeSplatting
  5. CascadingParameter
  6. CascadingParameter with Name

Thanks for reading!

--

--

Rikam Palkar - Microsoft MVP
Rikam Palkar - Microsoft MVP

Written by Rikam Palkar - Microsoft MVP

Making a world a better place by writing scalable code!! | Software engineer | Author | https://rikampalkar.github.io