b-state Blazor state manager
Mark Jack

Mark Jack @markjackmilian

About: Microsoft MCSD, Certified Xamarin Developer & Azure Solution Architect Expert. Building enterprise-grade solutions with cloud-native architecture.

Location:
Italy
Joined:
Nov 26, 2021

b-state Blazor state manager

Publish Date: May 6
1 0

When building modern web applications, managing state efficiently becomes crucial. In Blazor, as in other front-end frameworks, state management is key to ensuring that UI updates are predictable, scalable, and easy to maintain. That’s where b.state comes in — a lightweight, pipeline-based state manager designed specifically for Blazor applications.
b.state introduces a fresh, structured approach to handling state by organizing the flow of state changes through a customizable pipeline architecture. This design not only improves clarity and modularity but also enables the use of middleware, allowing developers to inject logic (such as logging, validation, or side-effects) at different stages of the state update process.

If you’re familiar with the Flux pattern (or Redux in the React ecosystem), you’ll find many familiar concepts in b.state, adapted to the Blazor architecture. Both follow a unidirectional data flow and rely on actions to describe state changes. In the table below, you can see a side-by-side comparison to help map concepts between the two approaches.

Image description

In this article, we’ll dive into how b.state works, why a pipeline-based model makes sense for state management, and how you can integrate middleware to build more robust and maintainable Blazor applications.

b-state Github Repo

In this introductory tutorial, we’ll replace the default Counter page from the Blazor template using BState. Let’s begin by creating a new Blazor WebAssembly project and adding the following NuGet package:

dotnet add package b-state
Enter fullscreen mode Exit fullscreen mode

In your Program.cs add a basic bstate startup (an advanced setup will be shown in the next story):

builder.Services.AddBState(configuration =>
{
    configuration.RegisterFrom(typeof(Program).Assembly);
});
Enter fullscreen mode Exit fullscreen mode

The RegisterFrom method ensure that all Actions and States are automatically registered into application services.
Create a new state called CounterState:

public partial class CounterState(IActionBus actionChannel) : BState(actionChannel)
{
    public int Counter { get; private set; } = 100;
}
Enter fullscreen mode Exit fullscreen mode

Thanks to the bstate.analyzer project, your IDE will show any discrepancies from project conventions as warnings:

  • Setters must be private inside bstate derived classes
  • IAction implementation must be subclasses of a bstate class

The next step is to define the Actions that can modify the CounterState, to do this, I added a CounterState.Actions.cs file with the partial class that contains all the state edit actions, in this case the only possible action is Add

public partial class CounterState
{
    record AddAction : IAction;
}
Enter fullscreen mode Exit fullscreen mode

Now it’s time to create the action that will modify the state, i created a new file called CounterState.AddAction.cs:

public partial class CounterState
{
    class AddActionHandler(CounterState counterState) : IActionHandler<AddAction>
    {
        public Task Execute(AddAction request)
        {
            counterState.Counter++;
            return Task.CompletedTask;
        }
    }

    public Task Add() => this.ActionChannel.Send(new AddAction());
}
Enter fullscreen mode Exit fullscreen mode

I implemented IActionHandler as a private class, incrementing the counter in the Execute method.
I also added a public Add() method that internally sends the AddAction.


bstate pipeline flow

When an IAction is executed through the ActionChannel, a pipeline is built to correctly manage the action.
Several elements are added to this pipeline: behaviors (which we will cover next time), preprocessors (also covered next time), the action executor (IActionHandler), and post-processors (which we will discuss later as well).
Once the pipeline execution is complete, a notification process is triggered to inform all components that use the part of the state affected by the action.

Image description


bstate component

Now, for the final step of this tutorial, we will create the component.
The component should inherit from BStateComponent and access one or more states by using the UseState method.
This will allow the component to automatically react to any changes in the state and update itself accordingly.

@using bstate.tutorial.Features.Counter
@inherits bstate.core.Components.BStateComponent

<p role="status">Current count: @State.Counter</p>

<button class="btn btn-primary" @onclick="Increment">Click me</button>

@code {
    CounterState State => this.UseState<CounterState>();
    Task Increment() => this.State.Add();
}
Enter fullscreen mode Exit fullscreen mode

This tutorial is just the first step in introducing how to implement state management using BState in a Blazor application.
In the next parts, we will explore more advanced topics, such as how to use behaviors, processors, and lifecycle extensions to further enhance the capabilities and flexibility of your components.


For a repo example of this tutorial see HERE, for a more complete example HERE
If you found this article helpful, leave a ⭐️ on the library’s repository on GitHub and follow me on GitHub, Twitter and Bluesky for more content.

Thanks for reading!

Comments 0 total

    Add comment