Optimizing Blazor performance using the @key directive

 
 
  • Gérald Barré

When Blazor renders a page, it first generates the expected DOM, then compares it with the current DOM to produce a diff. Finally, it applies that diff to bring the page in sync with the expected output.

The diffing algorithm identifies additions, edits, and deletions, then generates the commands needed to update the view. By default, it uses the element index to compare elements. While this works well in most cases, it can be suboptimal. For instance, inserting an element into a collection causes Blazor to treat every element from the insertion index onward as changed, with a new element appended at the end.

In the example below, all li elements are re-rendered every time an item is inserted at the first position of the list. The magenta-highlighted elements in the developer tools indicate which elements were updated.

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

The @key directive tells Blazor to use a specific key to identify elements instead of relying on their index. Blazor compares existing items with new ones using the key value, allowing it to more accurately detect additions, modifications, and deletions.

In the example below, only the newly inserted li is added. All other existing elements remain unchanged:

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

Note that diffing with the @key directive has a slightly higher computational cost. However, this is offset by the expense of DOM updates. For Blazor Server applications, fewer diffs also means less data transferred to the client over the WebSocket connection.

#Additional resources

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

Follow me:
Enjoy this blog?