Performance & Optimization
Optimize your Blazor apps with granular state subscriptions and selector patterns.
The Problem: Unnecessary Re-renders
By default, StoreComponent<TState> re-renders when any part of state changes. For large apps, this can cause performance issues.
In complex applications with frequent state updates, components may re-render hundreds of times per second, even when their displayed data hasn't changed.
The Solution: SelectorStoreComponent
Subscribe to only the data you need:
// ❌ Re-renders on ANY state change
@inherits StoreComponent<AppState>
<h1>@State.Counter</h1>
// ✅ ONLY re-renders when Counter changes
@inherits SelectorStoreComponent<AppState>
<h1>@State.Counter</h1>
@code {
protected override object SelectState(AppState state) => state.Counter;
}
Performance Impact
Real-world benchmark results from high-frequency update scenarios:
| Metric | Without Selectors | With Selectors |
|---|---|---|
| Re-renders/sec | ~250 | ~10-15 |
| CPU Usage | 40-60% | 5-10% |
| Frame Rate | 20-30 FPS | 60 FPS |
Up to 25x fewer re-renders in high-frequency scenarios.
Selector Patterns
Different selector patterns for common use cases:
Single Property
Select a single property from your state:
protected override object SelectState(AppState s) => s.UserName;
Multiple Properties (Tuple)
Combine multiple properties into a tuple:
protected override object SelectState(AppState s) => (s.UserName, s.IsLoading);
Computed Values (Record)
Create computed values from your state:
protected override object SelectState(TodoState s) => new TodoStats(
Total: s.Todos.Count,
Completed: s.Todos.Count(t => t.Completed)
);
Filtered Collections
Filter collections to only what you need:
protected override object SelectState(TodoState s) =>
s.Todos.Where(t => !t.Completed).ToImmutableList();
Performance Tips
Best practices for optimal performance:
Instead of multiple sequential updates, combine them into a single update operation.
Break large stores into focused domains to reduce the scope of state changes.
Use debouncing for high-frequency events like search input, resize, or scroll.
Load expensive data on-demand instead of loading everything upfront.
For components that don't need all state, use SelectorStoreComponent for granular updates.
Measure render counts before optimizing. Don't optimize prematurely.
Check out the Async Helpers section for utilities like UpdateDebounced, UpdateThrottled, and LazyLoad that can help with performance optimization.