Skip to main content
net10.0net8.0

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

Published
Oct 12, 2026
7d ago
Total Downloads
430
430

Install

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

README

ZeroAlloc.Flux

NuGet Build License: MIT AOT

ZeroAlloc.Flux is a source-generated, zero-allocation Flux/Redux state management library for .NET 8 and .NET 10. The Roslyn source generator wires all action dispatch at compile time β€” no reflection, no runtime dictionaries, no virtual dispatch. Dispatch hot path allocates 0 bytes per call when handlers complete synchronously.

Install

dotnet add package ZeroAlloc.Flux
dotnet add package ZeroAlloc.Flux.Blazor   # for Blazor apps

The Roslyn generator is bundled into the ZeroAlloc.Flux package β€” one PackageReference gives you both runtime contracts and the generator.

Quick start

using ZeroAlloc.Flux;

// 1. Define state β€” record struct (recommended) or record class.
[Feature]
public readonly partial record struct CounterState(int Count);

// 2. Define actions β€” plain record struct, no marker interface.
public readonly record struct IncrementAction(int Amount);
public readonly record struct ResetAction;

// 3. Define reducers β€” static methods, [Reducer] attribute.
public static partial class CounterReducers
{
    [Reducer]
    public static CounterState On(CounterState state, IncrementAction action)
        => state with { Count = state.Count + action.Amount };

    [Reducer]
    public static CounterState On(CounterState state, ResetAction _) => new(0);
}

// 4. Register + dispatch.
services.AddZeroAllocFlux();   // Scoped by default

var dispatcher = sp.GetRequiredService<IDispatcher>();
var counter = sp.GetRequiredService<IStore<CounterState>>();

await dispatcher.DispatchAsync(new IncrementAction(5));
Console.WriteLine(counter.Value.Count);   // 5

For Blazor:

public partial class Counter : FluxComponent
{
    [Inject] public IStore<CounterState> CounterStore { get; set; } = default!;
    [Inject] public IDispatcher Dispatcher { get; set; } = default!;

    protected override void SubscribeStores() => Subscribe(CounterStore);
}
<p>Count: @CounterStore.Value.Count</p>
<button @onclick="async () => await Dispatcher.DispatchAsync(new IncrementAction(1))">+</button>

FluxComponent re-renders when a store it subscribes to changes. Subscribe in SubscribeStores():

protected override void SubscribeStores() => Subscribe(CounterStore);

A component that overrides OnInitialized must call base.OnInitialized(), or it never subscribes.

Why ZeroAlloc.Flux

  • Compile-time dispatch. Every DispatchAsync<TAction> overload is generated from the discovered [Reducer] set. The dispatcher is a static switch β€” no dictionary lookups, no reflection.
  • Zero allocation hot path. Sync-completing dispatch returns a ValueTask.CompletedTask-equivalent β€” no state-machine box, no closure capture.
  • AOT-compatible. No reflection, no dynamic code. <IsAotCompatible>true</IsAotCompatible> enforced on every csproj.
  • Flux-coherent semantics. One action, many feature listeners β€” fan-out matches Fluxor/Redux conventions.
  • Effects are yours. 1.1.x ships no effects package. Write an effect as a service that injects IDispatcher, does its async work, and dispatches the result as another action.

Documentation

(Placeholder β€” full docs land in v1.0 release.)

License

MIT β€” see LICENSE.

Changes from Previous Version

v1.1.10v1.1.11

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.