Using the flux pattern (Fluxor) with Blazor

If you’ve done much with the likes of React you’ll probably know about the Flux pattern and implementations thereof, such as Redux and the Redux Toolkit (RTK). Well, There’s an implementation of the pattern for Blazor named Fluxor, let’s take a look at using this in our Blazor application.

Note: I’m using .NET 9 for this sample project.

I’m going to be leaning heavily on the Fluxor Tutorials to get started, so I’d definitely recommend checking them out.

  • Create yourself a Blazor application or use an existing one, I’m using a Blazor Standalone application for this post.
  • Add the NuGet packages
    • Fluxor
    • Fluxor.Blazor.Web
    • Fluxor.Blazor.Web.ReduxDevTools
  • In Program.cs add the line

    builder.Services.AddFluxor(options => 
       options.ScanAssemblies(typeof(Program).Assembly));
    
  • Add the following to the start of the App.razor file
    <Fluxor.Blazor.Web.StoreInitializer/>
    

    This initializes the store.

At this point we have the basics in place to use Fluxor, but now let’s see the store in work.

We’re going to start by implementing state for the sample Counter page. Again, please refer to the Fluxor Tutorials that cover this in more detail than I’m going to.

The Flux pattern

The In Depth Overview is a useful starting point as is The Fluxor Documentation to understand the Flux pattern.

Before we get into the code, let’s just review our understanding and expectations of Fluxor and the Flux pattern in general.

One important things to remember is function/methods such as the reducers should be pure functions. Data should therefore be immutable in that the data you send into the store and this any returned data will be a copy with any changes made on the copy.

Using the Blazor sample Counter page we have this workflow

  • Page intializes, we display an initial count
  • When the user clicks the button, we Dispatch an action via the Dispatcherreducer which then gets stored within the state.
  • The state updates so that anything watching it can update, hence the state updates and the UI then updates
    • Some code

      Let’s be a little boring and use the Counter.razor sample code.

      First off we’re create our CounterState.cs file

      [FeatureState]
      public class CounterState
      {
          public int ClickCount { get; }
      
          private CounterState() { } 
      
          public CounterState(int clickCount)
          {
              ClickCount = clickCount;
          }
      }
      

      We need a default ctor for initialization if the state, but this can be private. The other constructor will be used to create a new copy of the counter state.

      I’m going to stick to just using the .razor file, so within Counter.razor I’ve added

      @inject IState<CounterState> CounterState
      @inject IDispatcher Dispatcher
      

      Now we can simply using the following to get the current state

      @CounterState.Value.ClickCount
      

      When we click a button we’ll dispatch an action IncrementCounterAction like this

      private void IncrementCount()
      {
         Dispatcher.Dispatch(new IncrementCounterAction());
      }
      

      Where IncrementCounterAction is simply as follows

      public class IncrementCounterAction;
      

      Finally we need a reducer which accepts this action and this creates a copy of our updated data like this

      public static class Reducers
      {
          [ReducerMethod(typeof(IncrementCounterAction))]
          public static CounterState ReduceIncrementCounterAction(CounterState state) =>
              new CounterState(clickCount: state.ClickCount + 1);
      }
      

      We can write a reducer in a couple of other ways, for example

      public static class Reducers
      {
         [ReducerMethod]
         public static CounterState ReduceIncrementCounterAction(CounterState state, IncrementCounterAction action) =>
            new CounterState(clickCount: state.ClickCount + 1);
      }
      

      Or as follows

      public class IncrementCounterReducer : Reducer<CounterState, IncrementCounterAction>
      {
         public override CounterState Reduce(CounterState state, IncrementCounterAction action) =>
            new CounterState(clickCount: state.ClickCount + 1);
      }