API Reference

Complete API documentation for EasyAppDev.Blazor.Store.

StoreComponent<TState>

Base component class that provides automatic state subscription and reactivity. Inherit from this class to get access to state and update methods.

Definition
public abstract class StoreComponent<TState> : ComponentBase
{
    // State access
    protected TState State { get; }

    // Core updates
    protected Task Update(Func<TState, TState> updater, string? action = null);
    protected Task UpdateAsync(Func<TState, Task<TState>> asyncUpdater, string? action = null);

    // Async helpers
    protected Task UpdateDebounced(Func<TState, TState> updater, int delayMs, string? action = null);
    protected Task UpdateThrottled(Func<TState, TState> updater, int intervalMs, string? action = null);
    protected Task ExecuteAsync<T>(
        Func<Task<T>> action,
        Func<TState, TState> loading,
        Func<TState, T, TState> success,
        Func<TState, Exception, TState>? error = null);
    protected Task<T> LazyLoad<T>(string key, Func<Task<T>> loader, TimeSpan? cacheFor = null);
}

Properties

State

Gets the current state. Automatically updated when the store changes.

protected TState State { get; }

Methods

Update

Updates the state synchronously using a transformation function.

protected Task Update(Func<TState, TState> updater, string? action = null)

Parameters:

  • updater - Function that takes current state and returns new state
  • action - Optional action name for DevTools and logging

Example:

await Update(s => s.Increment(), "INCREMENT");

UpdateAsync

Updates the state asynchronously using an async transformation function.

protected Task UpdateAsync(Func<TState, Task<TState>> asyncUpdater, string? action = null)

Example:

await UpdateAsync(async s => await s.LoadUserAsync(id), "LOAD_USER");

UpdateDebounced

Debounces state updates. Multiple rapid calls within the delay period will result in only the last update being applied.

protected Task UpdateDebounced(Func<TState, TState> updater, int delayMs, string? action = null)

Parameters:

  • updater - State transformation function
  • delayMs - Debounce delay in milliseconds
  • action - Optional action name

Example:

<input @oninput="@(e => UpdateDebounced(s => s.SetQuery(e.Value?.ToString() ?? ""), 300))" />

UpdateThrottled

Throttles state updates. Ensures updates happen at most once per interval.

protected Task UpdateThrottled(Func<TState, TState> updater, int intervalMs, string? action = null)

Parameters:

  • updater - State transformation function
  • intervalMs - Throttle interval in milliseconds
  • action - Optional action name

Example:

<div @onmousemove="@(e => UpdateThrottled(s => s.SetPosition(e.ClientX, e.ClientY), 100))">

ExecuteAsync

Executes an async operation with automatic state management for loading, success, and error states.

protected Task ExecuteAsync<T>(
    Func<Task<T>> action,
    Func<TState, TState> loading,
    Func<TState, T, TState> success,
    Func<TState, Exception, TState>? error = null)

Parameters:

  • action - Async operation to execute
  • loading - State transformation for loading state
  • success - State transformation for success with result
  • error - Optional state transformation for error handling

Example:

await ExecuteAsync(
    () => UserService.LoadAsync(id),
    loading: s => s with { User = s.User.ToLoading() },
    success: (s, user) => s with { User = AsyncData.Success(user) },
    error: (s, ex) => s with { User = AsyncData.Failure(ex.Message) }
);

LazyLoad

Loads and caches data with automatic request deduplication. If multiple components request the same data simultaneously, only one request is made.

protected Task<T> LazyLoad<T>(string key, Func<Task<T>> loader, TimeSpan? cacheFor = null)

Parameters:

  • key - Unique cache key
  • loader - Function to load the data
  • cacheFor - Optional cache expiration (default: 5 minutes)

Example:

var user = await LazyLoad(
    $"user-{userId}",
    () => UserService.GetUserAsync(userId),
    TimeSpan.FromMinutes(5)
);

SelectorStoreComponent<TState>

Advanced component that subscribes to only specific parts of the state. Use this for performance optimization to avoid unnecessary re-renders.

Definition
public abstract class SelectorStoreComponent<TState> : ComponentBase
{
    protected TState State { get; }
    protected object? Selected { get; }

    // Required: Override to select specific state slice
    protected abstract object SelectState(TState state);

    // Update methods (no async helpers)
    protected Task Update(Func<TState, TState> updater, string? action = null);
}

Properties

State

Gets the full current state.

Selected

Gets the selected slice of state returned by SelectState.

Methods

SelectState (Abstract)

Override this method to select the specific part of state you want to monitor. The component will only re-render when this selected value changes.

protected abstract object SelectState(TState state)

Examples:

// Single property
protected override object SelectState(AppState s) => s.UserName;

// Multiple properties (tuple)
protected override object SelectState(AppState s) => (s.UserName, s.IsLoading);

// Computed values (record)
protected override object SelectState(TodoState s) => new TodoStats(
    Total: s.Todos.Count,
    Completed: s.Todos.Count(t => t.Completed)
);

Registration Methods

Methods to register stores in your dependency injection container.

AddStoreWithUtilities (Recommended)

Registers a store with all utility services (debounce, throttle, cache, async executor) in one call.

builder.Services.AddStoreWithUtilities(
    new MyState(),
    (store, sp) => store.WithDefaults(sp, "MyStore"));

AddStore

Registers a singleton store. Requires manual registration of utilities if you want to use async helpers.

// Manual registration
builder.Services.AddStoreUtilities();  // Required for async helpers
builder.Services.AddAsyncActionExecutor<MyState>();  // Required for ExecuteAsync
builder.Services.AddStore(
    new MyState(),
    (store, sp) => store.WithDefaults(sp, "MyStore"));

AddScopedStore / AddScopedStoreWithUtilities

Registers a scoped store (Blazor Server scenarios).

builder.Services.AddScopedStoreWithUtilities(
    new SessionState(),
    (store, sp) => store.WithDefaults(sp, "Session"));

AddTransientStore / AddTransientStoreWithUtilities

Registers a transient store (new instance per injection).

builder.Services.AddTransientStoreWithUtilities(
    () => new TempState(),
    (store, sp) => store.WithDefaults(sp, "Temp"));

StoreBuilder Configuration

Fluent methods for configuring your store.

WithDefaults

Configures store with DevTools, logging middleware, and JSRuntime integration in one call.

(store, sp) => store.WithDefaults(sp, "StoreName")

Equivalent to:

store
    .WithDevTools("StoreName")
    .WithLogging()
    .WithJSRuntime(sp.GetRequiredService<IJSRuntime>())

WithPersistence

Enables automatic persistence to LocalStorage or SessionStorage.

(store, sp) => store
    .WithDefaults(sp, "MyStore")
    .WithPersistence(sp, "storage-key")  // LocalStorage by default

State is automatically saved on updates and restored on app load.

WithDiagnosticsIfAvailable

Adds diagnostics middleware (DEBUG builds only, compiled out in production).

// Program.cs
builder.Services.AddStoreDiagnostics();

builder.Services.AddStore(
    new MyState(),
    (store, sp) => store
        .WithDefaults(sp, "MyStore")
        .WithDiagnosticsIfAvailable(sp));

Tracks action history, performance metrics, and subscriptions. Zero overhead in production.

WithMiddleware

Adds custom middleware for state update interception.

(store, sp) => store
    .WithDefaults(sp, "MyStore")
    .WithMiddleware(new CustomMiddleware<MyState>())

Complete Configuration Example

Program.cs
// All-in-one registration with utilities
builder.Services.AddStoreWithUtilities(
    new MyState(),
    (store, sp) => store
        .WithDefaults(sp, "MyStore")         // DevTools + Logging + JSRuntime
        .WithPersistence(sp, "my-state")     // LocalStorage auto-save
        .WithDiagnosticsIfAvailable(sp)      // Diagnostics (DEBUG only)
        .WithMiddleware(customMiddleware));  // Custom middleware

Quick Reference

API Purpose Code Reduction
StoreComponent<T> Base component with auto-subscription -
SelectorStoreComponent<T> Granular subscriptions (performance) 25x fewer re-renders
Update() Sync state updates -
UpdateAsync() Async state updates -
UpdateDebounced() Debounced updates (search, input) 94%
UpdateThrottled() Throttled updates (scroll, mouse) 95%
ExecuteAsync() Automatic error handling 58%
LazyLoad() Caching + deduplication 85%
AsyncData<T> Async state management 95%
AddStoreWithUtilities() All-in-one registration -
WithDefaults() DevTools + Logging + JSRuntime -
WithPersistence() LocalStorage auto-save -
Need More Details?

Check out the Getting Started guide for practical examples, or explore Async Helpers for in-depth documentation on async operations.