Optimizing Blazor performance using the @key directive

 
 
  • Gérald Barré

When Blazor renders a page, it first generates the expected DOM. Then, it compares this expected DOM with the current DOM and it generates a diff. Finally, it applies the diff so the page corresponds to the expected one.

The diffing algorithm must find the additions/editions/deletions, and generate the right commands to update the view. By default, it uses the element index to compare elements. While this works great in most cases, it is sometimes not optimal. For instance, if you insert an element in a collection, it will detect that every element starting at the insertion index is changed and a new one is added at the end.

In this example, you can see that all li elements are refreshed every time an item is inserted at the first position of the list. This is represented by the fact that the elements are in magenta in the developer tools.

Razor
<ul>
    @foreach (var item in items)
    {
        <li>@item</li>
    }
</ul>

The @key directive allows instructing Blazor to use a specific key to compare elements instead of using the index. Blazor will compare the existing items with the new ones using the value of the key. This way it will better detect additions/modifications/deletions.

In this example, you can see that only the new li is inserted. Other existing elements are unmodified:

Razor
<ul>
    @foreach (var item in items)
    {
        <li @key="item.Id">@item</li>
    }
</ul>

Note that diffing using the @key directive is a little more expensive. However, this is compensated by the fact that updating the DOM is expensive. In the case of Blazor Server, sending the diffs to the client using the WebSocket is also more expensive if there are more diffs to send to the client.

#Additional resources

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub