Blex for Blazor
Blazor state management

State management that gets out of the way

Blex is a lightweight, source-generator-powered state library for Blazor. You write one [BlexState] field and one [BlexAction] method; the generator writes the reactive properties, the dispatch plumbing, the JSON snapshots and the loading/error lifecycle. Redux DevTools time-travel is built in.

The whole store

This is not an excerpt - it is a complete, working store. There are no action classes, no reducers, no feature registrations and no selector boilerplate.

C#
CounterStore.cs
[BlexStore(Name = "counter", Persist = true)]
public partial class CounterStore
{
    [BlexState] private int _count;
    [BlexState] private int _step = 1;

    [BlexComputed] private int  ComputeDoubleCount() => Count * 2;
    [BlexComputed] private bool ComputeIsEven()      => Count % 2 == 0;

    [BlexAction] private void OnIncrement()       => Count += Step;
    [BlexAction] private void OnDecrement()       => Count -= Step;
    [BlexAction] private void OnSetStep(int step) => Step = step;
}

From that, the generator emits:

  • reactive Count / Step properties whose setters flow through the dispatch pipeline,
  • memoized DoubleCount / IsEven accessors that invalidate themselves on every state change,
  • public Increment(), Decrement() and SetStep(int) wrappers that batch their mutations into one named, recorded action,
  • SerializeState() / DeserializeState() for snapshots, persistence and time-travel,
  • and the BlexStoreBase base type itself.
Live demo That store, running right now

This is the very store shown above, resolved from DI. Open the Inspector at the bottom of the page to watch the actions stream in.

Count 0
DoubleCount 0
IsEven True
Step 1

This store is marked Persist = true - reload the page and the count survives.

Why it exists

Fluxor is the de-facto Redux implementation for Blazor, and it works - but a single counter costs you a state class, an action class, a reducer and often an effect class, and there is no first-class DevTools time-travel. Blex keeps what makes Flux good - one observable state tree, named actions, a middleware pipeline - and deletes the ceremony with a Roslyn incremental generator.

TaskFluxorBlex
Define a piece of stateFeature + State classone [BlexState] field
Define an actionAction class + Reducer methodone [BlexAction] method
Action payloads in DevTools / middlewaremanualautomatic (ctx.Args)
Derived statemanual selectors[BlexComputed], memoized
Async side-effectsEffect classes[BlexEffect] with generated loading/error
Effect cancellation & concurrencymanualCancellationToken + Latest/Drop/Queue
Ad-hoc batched mutations✗store.Batch(name, …)
Reset to initial statemanualstore.ResetState()
Granular re-rendermanual selectorsselector Subscribe(…)
Normalized collectionsmanualBlexEntityAdapter / BlexEntityState
Persistence3rd-partybuilt in, with debounce + migrations
Undo / redo✗BlexHistory
Redux DevTools time-travel✗✓ built in
Test helpers✗Bit.Blex.Testing harness
Boilerplatehighgenerated away

What's in the box

Packages

Package Description
Bit.Blex The core runtime: BlexStoreBase, attributes, dispatch, middleware, persistence, entity adapter, undo/redo and BlexManager. No JS dependency.
Bit.Blex.Generators The Roslyn incremental generator that writes the store plumbing. Reference it next to Bit.Blex; it ships as an analyzer only.
Bit.Blex.Blazor Blazor integration: <BlexProvider>, BlexComponentBase, browser-storage persistence and the Redux DevTools bridge.
Bit.Blex.Maui .NET MAUI integration: UseBitBlex() startup initializer, Preferences-backed persistence and XAML-bindable stores.
Bit.Blex.Testing Test harness and assertions: BlexTestHarness, BlexActionLog, WaitForAsync.

The docs site is the demo

Every page here runs against real stores registered in this app's Program.cs. The Inspector at the bottom of the window shows the live action feed, the serialized global state tree, the undo stack and the error sink - all fed by the same public APIs you are reading about.

An unhandled error has occurred. Reload 🗙