Skip to main content
net10.0net8.0

Blazor host adapter for ZeroAlloc.Flux β€” FluxComponent base class and DI extensions.

Published
Oct 16, 2026
4d ago
Total Downloads
430
430

Install

dotnet add package ZeroAlloc.Flux.Blazor --version 1.2.2
ProductVersions
.NET
net10.0net8.0

README

ZeroAlloc.Flux

NuGet Build License: MIT AOT GitHub Sponsors

Source-generated Flux/Redux state management for .NET and Blazor, an alternative to Fluxor: no reflection, no allocations when you dispatch, NativeAOT-ready.

Why ZeroAlloc.Flux

  • 0 B per dispatch. Dispatching an action, fanning it out to several features, notifying subscribers and reading the state allocate nothing; tests assert each path on net8.0 and net10.0, including dispatch to a store that a Blazor FluxComponent subscribes to.
  • Dispatch is generated code. The dispatcher is built at compile time from your [Reducer] methods and resolves to a direct call per action type: no handler dictionary, no reflection.
  • Works under NativeAOT and trimming. CI publishes and runs a NativeAOT app, and builds a Blazor WebAssembly app, on every build.
  • Compile-time diagnostics. A wrong reducer signature, a duplicate reducer or a feature that is not partial stops the build with a ZFLUX error instead of failing at runtime.

Install

dotnet add package ZeroAlloc.Flux

The source generator ships inside the package. A console app also needs a DI container, for example dotnet add package Microsoft.Extensions.DependencyInjection; ASP.NET Core and Blazor already have one.

Quick start

using Microsoft.Extensions.DependencyInjection;
using ZeroAlloc.Flux;
using ZeroAlloc.Flux.Generated;

using var sp = new ServiceCollection().AddZeroAllocFlux().BuildServiceProvider();
var dispatcher = sp.GetRequiredService<IDispatcher>();
var counter = sp.GetRequiredService<IStore<CounterState>>();

counter.StateChanged += state => Console.WriteLine($"Count is now {state.Count}");

await dispatcher.DispatchAsync(new Increment(5));  // Count is now 5
await dispatcher.DispatchAsync(new Increment(3));  // Count is now 8

[Feature]
public readonly partial record struct CounterState(int Count);

public readonly record struct Increment(int Amount);

public static class CounterReducers
{
    [Reducer]
    public static CounterState On(CounterState state, Increment action)
        => state with { Count = state.Count + action.Amount };
}

State is a record, actions are plain types with no marker interface, and reducers are static methods. The generator writes the store, the dispatcher and AddZeroAllocFlux.

What you get

  • Stores per state slice, safe for concurrent dispatch and reads, with a StateChanged event. Core concepts
  • One action, many features: every reducer for an action runs, as in Redux and Fluxor.
  • Custom initial state through a factory that can use your services. Initial state
  • Effects as plain services that inject IDispatcher, do async work and dispatch the result. Effects
  • Blazor support: ZeroAlloc.Flux.Blazor adds FluxComponent, which re-renders when a store it subscribes to changes. Blazor guide
  • Build-time checks, ZFLUX001 to ZFLUX009. Diagnostics
  • Targets net8.0 and net10.0.

Performance

Exact allocation budgets, each asserted by an AllocationGate test over 1,000 calls in CI:

Hot path Allocated
DispatchAsync to one record struct feature 0 B
DispatchAsync fanned out to two features, each raising StateChanged to a subscriber 0 B
IStore<TState>.Value read 0 B

The budgets hold for the library's own work; a record class feature allocates the new state your reducer returns. What still allocates, why dispatch does not, and how to run the benchmarks: docs/performance.md.

Learn more

Changes from Previous Version

No structural changes between v1.2.1 and v1.2.2.

Adoption Assessment

Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.

Compatibility metadata lists 2 target frameworks; confirm the exact target used by your application.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.