Advanced Blazor State Management Using Fluxor, part 2 - Starting with Fluxor
Tags: csharp, blazor
Published: 2021-03-06 23:32:47

> This is the second in a short series of blog posts where I will go beyond the introductory level and dig a bit deeper into using the Fluxor library in a Blazor Wasm project. If you haven't read the previous posts, [please start there](https://dev.to/mr_eking/advanced-blazor-state-management-using-fluxor-part-1-696).

Let's get to some code, shall we?

I'll be illustrating these examples using the Blazor WebAssembly, ASP.NET hosted template in [Visual Studio 2019 Community](https://visualstudio.microsoft.com/downloads/). I'm a big Visual Studio, so that's my preferred IDE, but you can use [Visual Studio Code](https://code.visualstudio.com/) instead if you prefer. Just execute `dotnet new blazorwasm -ho` in the command shell. The `-ho` indicates the "ASP.NET Core hosted" option. In Visual Studio 2019, this is what I'm using:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r70k3n6fno389ipmkc2h.png)

If you build and run at this point, you'll see an application with a Counter page that exhibits the state-losing behavior I noted in the previous blog post:

![Counter component losing state after navigation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ylqvr726a12y4on5pj95.gif)

### Installing Fluxor

Before we begin: The code for this blog series can be found on github as shown below. To check your progress for this step of the series, view the [002_Add_Fluxor_Libraries branch](https://github.com/eric-king/BlazorWithFluxor/tree/002_Add_Fluxor_Libraries).

{% github eric-king/BlazorWithFluxor no-readme %}

To add Fluxor to the project and begin our state-management journey, first install the [Fluxor.Blazor.Web Nuget package](https://www.nuget.org/packages/Fluxor.Blazor.Web) to the `.Client` project in the solution:

```csharp
Install-Package Fluxor.Blazor.Web
```

Alter the `Program.cs` file to include this line, just above the line that begins "await builder.Build()"

```csharp
builder.Services.AddFluxor(o => o.ScanAssemblies(typeof(Program).Assembly));
```

and the accompanying `using` statement at the top:

```csharp
using Fluxor;
```

For convenience, add a couple of Fluxor using statements to the `_Imports.razor` file:

```csharp
@using Fluxor
@using Fluxor.Blazor.Web.Components
```

To initialize Fluxor when the application is started, we add this to the very top of the `App.razor` file:

```xml
<Fluxor.Blazor.Web.StoreInitializer />
```

And finally, update the `wwwroot/index.html` to include just above the `</body>` tag:

```html
<script src="_content/Fluxor.Blazor.Web/scripts/index.js"></script>
```

And with that, Fluxor is ready to be used. Let's update the Counter page to take advantage.

>**Note**: This is the first point at which I diverge from the introductory videos I referred to in part 1 of this series. They both proceed by creating a "Store" folder at the root of the project, with a "Counter" subfolder, and placing the Counter Store files there. I prefer the feature-oriented folder structure that follows.

### Creating the Counter Store

Create a folder at the root of the solution named `Features`, and another folder inside of it named `Counter`. This will be the place where we keep all of the files related to the Counter.

In the `Counter` folder create two more folders named `Pages` and `Store`. Move the `Counter.razor` file from the `\Pages` folder into the `\Features\Counter\Pages` folder. Your Client project should look like:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80keudkw0lg89onh0qsl.png)

Next let's create the Store. 

A Fluxor Store consists of 5 pieces:
1. The `State` record
2. The `Feature` class
3. One or more `Action` classes
4. The `Reducers` class
5. The `Effects` class

>**Note**: This is the second place where I significantly diverge from the introductory videos. They follow the common C# convention of 'one class per file', which I usually also follow, but I think this situation, where none of these classes should really exist without all of the others, is a good example of when it's fine to group multiple classes together in the same file.

In the `\Features\Counter\Store` folder create a file named `CounterStore.cs`. Remove the `class CounterStore`; we're not going to need it. This file will instead hold all of the Store pieces listed above.

In the new `CounterStore` file, add a `record` to store the state of the Counter. We only need to track one property: the current count.

```csharp
public record CounterState 
{
    public int CurrentCount { get; init; }
}
```
Note the CurrentCount property doesn't have a setter. It's inherently read-only, as is the intention in the Flux pattern.

Below the state we add the `Feature` class to expose the CounterState to Fluxor. This will require a `using Fluxor;` statement at the top of the file.

```csharp
public class CounterFeature : Feature<CounterState>
{
    public override string GetName() => "Counter";

    protected override CounterState GetInitialState()
    {
        return new CounterState 
        {
            CurrentCount = 0
        };
    }
}

```

The Fluxor class `Feature<T>` has two abstract methods we must implement. One returns the name that Fluxor will use for the feature, and here I recommend a simple human-readable string that will uniquely identify the feature for this application. The second sets up the initial state of the `State`. We'll start with a `CurrentCount` of zero.

Now we need an `Action` to dispatch when the button is clicked, instructing the store to increment the counter. Below the Feature, add this class:

```csharp
public class CounterIncrementAction {}
```

This class doesn't need any properties, since its name includes all the information needed by the Store to know what to do.

>**Note**: I recommend a naming convention for `Actions` in the form of `FeatureActivityAction` where `Feature` in this case is "Counter", `Activity` is "Increment", and `Action` distinguishes the class as an Action. The reason for this is that eventually you may have a lot of Features, and if many of them have an Action class named `public class Initialize {}` then there is a decent chance of name clashes and confusion later. Naming your Actions this way keeps that from happening and makes it easy to keep track of all the pieces of the Store.

And finally, we need a `Reducer` method to handle the `CounterIncrementAction` when it is dispatched. Add this class to the Store file:

```csharp
public static class CounterReducers 
{
    [ReducerMethod(typeof(CounterIncrementAction))]
    public static CounterState OnIncrement(CounterState state) 
    {
        return state with
        {
            CurrentCount = state.CurrentCount + 1
        };
    }
}
``` 

Note that this is a `static` class, and the `ReducerMethod` is a `static` method. This is intentional since a Reducer method should be a pure method with no side effects. It takes in the current State (the `CounterState state` parameter) and returns a new State with new values based on the Action it's handling. The Reducers class itself contains no state.

There are two ways to declare a ReducerMethod as it relates to the Action it is subscribing to. The most common way is to provide both the State and the Action as parameters to the method, like so:

```csharp
[ReducerMethod]
public static CounterState OnIncrement(CounterState state, CounterIncrementAction action) 
{
    /// code
}
```

However, in the case of an Action with no payload, such as with `CounterIncrementAction`, the `action` parameter will not be referenced in the body of the method. Depending on your compiler settings, this may result in an 'unused parameter' warning. The alternative `[ReducerMethod(typeof(Type))]` attribute that takes an Action Type is a way of providing the same behavior without the compiler warning.

>**Note**: I recommend a naming convention of `OnActivity` for the names of the Reducer methods. The name of the Reducer class and methods don't really matter to Fluxor, as they're identified by scanning for `[ReducerMethod]` attributes, but having a consistent and meaningful name is useful to the developers working on the application. Having a `FeatureActivityAction` action handled by an `OnActivity` Reducer method is easy to remember and understand.

With all of these pieces in place, the `CounterStore.cs` file should look like this:

```csharp
using Fluxor;

namespace BlazorWithFluxor.Client.Features.Counter.Store
{
    public record CounterState 
    {
        public int CurrentCount { get; init; }
    }

    public class CounterFeature : Feature<CounterState>
    {
        public override string GetName() => "Counter";

        protected override CounterState GetInitialState()
        {
            return new CounterState 
            {
                CurrentCount = 0
            };
        }
    }

    public class CounterIncrementAction {}

    public static class CounterReducers 
    {
        [ReducerMethod(typeof(CounterIncrementAction))]
        public static CounterState OnIncrement(CounterState state) 
        {
            return state with
            {
                CurrentCount = state.CurrentCount + 1
            };
        }
    }

}
```

### Updating the View

With the CounterStore in place, we're ready to update the `Counter.razor` page to use it.

In the `Counter.razor` file, just under the `@page "/counter"` directive, add:

```csharp
@inherits FluxorComponent
```

This allows the Counter component to access the Fluxor resources.

Since we're going to need to reference the CounterStore, we need to add a `using` statement:

```csharp
@using BlazorWithFluxor.Client.Features.Counter.Store
```

We'll need to access the CounterState, and in order to dispatch Actions we'll need a Fluxor Dispatcher, so we inject these:

```csharp
@inject IDispatcher Dispatcher
@inject IState<CounterState> CounterState
```

We remove the local count property and replace it with a reference to `@CounterState.Value.CurrentCount` (the `IState<T>` wrapper exposes the wrapped state object using the `.Value` property) and replace the `counter++` with a call to `Dispatcher.Dispatch(new CounterIncrementAction());`. The resulting file should look like:

```csharp
@page "/counter"
@inherits FluxorComponent

@using BlazorWithFluxor.Client.Features.Counter.Store

@inject IDispatcher Dispatcher
@inject IState<CounterState> CounterState

<h1>Counter</h1>

<p>Current count: @CounterState.Value.CurrentCount</p>

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

@code {
    private void IncrementCount()
    {
        Dispatcher.Dispatch(new CounterIncrementAction());
    }
}
```

If we build and run the application, we should see the fruits of our labor:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jffj887ds1917jkexr3p.gif)

### Other components

Once the `CounterStore` is set up and running, it's not just the `Counter.razor` component that has access to it; any component in the application can reference it. As an example, let's the CurrentCount to the Nav Menu.

Update the `\Shared\NavMenu.razor` component to include the necessary Fluxor hooks at the top of the file:

```csharp
@inherits FluxorComponent
@using BlazorWithFluxor.Client.Features.Counter.Store
@inject IState<CounterState> CounterState
```

Then change the NavLink label from `Counter` to `Counter (@CounterState.Value.CurrentCount)`, getting a read-only reference to the `CurrentCount` property of `CounterState`.

Build, run, and voilà:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2jzk60k718nl0vutr4kq.gif)

It's that easy.

### ReduxDevTools

Ok, one more thing before moving on to the more advanced stuff.

Fluxor also supports the [ReduxDevTools](https://github.com/zalmoxisus/redux-devtools-extension) browser extension. To enable it, first install the [NuGet package Fluxor.Blazor.Web.ReduxDevTools](https://www.nuget.org/packages/Fluxor.Blazor.Web.ReduxDevTools):

```csharp
Install-Package Fluxor.Blazor.Web.ReduxDevTools
```

And enable it in the `Program.cs` by adding `.UseReduxDevTools()` to the AddFluxor options like so:

```csharp
builder.Services.AddFluxor(o => o.ScanAssemblies(typeof(Program).Assembly).UseReduxDevTools());
```

After all of these steps, the solution should look like [this branch of the demo repository](https://github.com/eric-king/BlazorWithFluxor/tree/004_Cross_Component_Store_Sharing).

In the next part of this series, I will "featurize" the template's Weather Forecasts component while using a Fluxor `Effect` method.