Course contentsShow
← C#
Lesson 1421 of 1,90812. Modern Frontend with Razor and BlazorFree lesson

Optimizing Rendering Logic

Learn when to manually call StateHasChanged to optimize update performance.

In this lesson, you will learn how to bypass Blazor’s automatic UI refresh cycle to improve performance by manually invoking StateHasChanged.

The Automatic Rendering Trap

By default, Blazor is "eager." Whenever an event handler completes (like a button click) or a lifecycle method finishes, Blazor automatically runs StateHasChanged to compare your component’s current state with its previous state and updates the DOM accordingly.

While convenient, this is often overkill. If you have a component performing high-frequency background updates—such as processing a stream of sensor data or handling complex asynchronous calculations—letting the framework re-render the entire component after every micro-update can lead to stuttering or UI lag.

Controlling the Refresh

To optimize, you can override ShouldRender() to return false by default. This tells Blazor to stop re-rendering the component automatically. Once you’ve taken control, you only call StateHasChanged() when you are ready to "flush" your state changes to the UI.

Consider this high-frequency counter:

protected override bool ShouldRender() => false; // Disable auto-render

private async Task UpdateValue(int newValue)
{
    _value = newValue;

    // Only update the UI once every 100 updates, or based on specific business logic
    if (_value % 100 == 0)
    {
        await InvokeAsync(StateHasChanged);
    }
}

When to Use This

Manually triggering renders is not for every component; it is a specialized tool for performance-critical scenarios. Use it when:

  1. High-Frequency Events: Your component reacts to events firing many times per second (e.g., mouse movement, socket messages).
  2. Batch Processing: You are performing many internal data mutations that don't need to be reflected in the UI until a specific condition is met.
  3. Expensive Rendering: Your component subtree contains complex logic or heavy markup that is computationally expensive to diff and update.

By silencing the automatic render cycle, you reduce the workload on the browser's diffing engine and keep the main thread available for more important interactions.

Key Takeaway: Overriding ShouldRender allows you to stop Blazor’s automatic UI updates, giving you manual control to trigger StateHasChanged only when a user-visible change is actually necessary.