Core Concepts
Understanding the fundamental principles of EasyAppDev.Blazor.Store will help you build better Blazor applications with simple, type-safe state management.
State = Immutable Record
State in EasyAppDev.Blazor.Store is defined as immutable C# records with transformation methods. This pattern ensures predictability, testability, and type safety.
public record TodoState(ImmutableList<Todo> Todos)
{
public static TodoState Initial => new(ImmutableList<Todo>.Empty);
public TodoState AddTodo(string text) =>
this with { Todos = Todos.Add(new Todo(Guid.NewGuid(), text, false)) };
public TodoState ToggleTodo(Guid id) =>
this with {
Todos = Todos.Select(t =>
t.Id == id ? t with { Completed = !t.Completed } : t
).ToImmutableList()
};
}
- Pure functions - State methods have no side effects and no I/O operations
- Always use
withexpressions - Never mutate state directly - Use
ImmutableList<T>- For collections that need to be modified - Co-locate transformation logic - Keep state methods with state data
StoreComponent = Automatic Reactivity
By inheriting from StoreComponent<TState>, your components get automatic subscription to state changes and reactive updates without any manual wiring.
Automatic Subscription
Components automatically subscribe to state changes on initialization
State Property
Access current state directly via the State property
Update Method
Call Update() to apply state transformations
Automatic Cleanup
Subscriptions are disposed when component is destroyed
@inherits StoreComponent<TodoState>
<button @onclick="AddTodo">Add</button>
@code {
async Task AddTodo() => await Update(s => s.AddTodo("New task"));
}
Update Flow
Understanding how state updates flow through the system helps you reason about your application's behavior.
Component calls Update()
Your component calls Update(s => s.Method()) with a transformation function
await Update(s => s.Increment())
Store applies transformation
The store acquires a lock and applies your transformation function to the current state
New state created
A new immutable state object is created. The old state remains unchanged
This ensures you can always safely compare or rollback states!
All subscribers notified
Every component subscribed to this store receives the new state
Components re-render
Each subscribed component automatically triggers StateHasChanged() and re-renders with the new state
Key Principles Summary
โ Do
- Use C# records for all state
- Use
withexpressions for updates - Keep state methods pure (no side effects)
- Use
ImmutableList<T>andImmutableDictionary<K,V> - Inherit from
StoreComponent<T>for automatic reactivity - Call
Update()with transformation functions
โ Don't
- Mutate state properties directly
- Use mutable collections like
List<T> - Add side effects to state methods
- Call APIs or log from state methods
- Forget to use
awaitwithUpdate() - Manually subscribe/unsubscribe from stores