redux-net-un-contendor-de-estado-para-aplicaciones-net

Redux.NET, a state container for .NET applications

  • 4 min

Redux.NET is a predictable state container for .NET applications based on the Redux development for JS https://github.com/reactjs/redux.

Redux is a popular Open Source library for JavaScript https://github.com/reactjs/redux, which has inspired many other frameworks like Vuex for VueJs.

Redux.NET brings the philosophy of these state containers, whose purpose is to abstract the state of an application, so that it can be easily shared by all components of an application.

When developing an application in MVVM, one of the first common concerns is how to exchange information between the components of an application while keeping the coupling between classes loose.

Thus, we have several options usually available, including the publisher-subscriber pattern (Messenger), inversion of control (IoC), and dependency injection.

Redux.NET is an alternative or complement to these methodologies. According to the Redux philosophy, the state container is “predictable” because it meets 3 conditions.

The state is unique for the entire application

The state is read-only

The change from one state to another is performed through actions

To achieve this, the operation of Redux.NET (like Redux) is based on three components,

  • Store, stores the application state in an object T
  • Actions, are called by our objects to perform actions on the Store.
  • Reducers, define the transitions between one state and another when receiving an action

The library provides several examples to illustrate its use. Let’s explain the most important parts of the simplest one, the ‘Counter’ example, which simply contains a counter that increments or decrements its value.

First, in the App class we have defined an IStoresince in this simple example the only variable that identifies the application state is the counter value.

public sealed partial class App : Application
{
  public static IStore<int> CounterStore { get; private set; }

  public App()
  {
    InitializeComponent();
    
    CounterStore = new Store<int>(CounterReducer.Execute, 0);
  }

  protected override void OnLaunched(LaunchActivatedEventArgs e)
  {
    // omitted for example
  }
}
Copied!

On the other hand, we have defined in a file the actions that our Store accepts, and which will be triggered from the ViewModel.

public class IncrementAction : IAction { }

public class DecrementAction : IAction { }
Copied!

The necessary Reducer is also defined, which determines the next state based on the current state and the received action. In this example, the new state simply increments/decrements the variable, respectively.

public static class CounterReducer
{
  public static int Execute(int previousState, IAction action)
  {
    if(action is IncrementAction)
    {
      return previousState + 1;
    }

    if(action is DecrementAction)
    {
      return previousState - 1;
    }

    return previousState;
  }
}
Copied!

With all this defined, we will now see how to call it from the ViewModel (in this case from the UI, because the provided example is very simple).

As we can see, the Increment and Decrement buttons use the Store, to which they send the previously defined actions.

On the other hand, in the constructor, we subscribe to state changes. In this example, the counter value is simply updated to the new state.

public sealed partial class MainPage : Page
{
  public MainPage()
  {
    this.InitializeComponent();

    App.CounterStore.Subscribe(counter => CounterRun.Text = counter.ToString());
  }

  private void IncrementButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
  {
    App.CounterStore.Dispatch(new IncrementAction());
  }

  private void DecrementButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
  {
    App.CounterStore.Dispatch(new DecrementAction());
  }
}
Copied!

It’s a very simple example but it introduces the three fundamental elements (Store, Actions, and Reducers). It’s easy to extrapolate this example to a real project, where the Store would have a more complex object containing the necessary variables to represent the application state.

Certainly, Redux.NET is an interesting library, although it requires a change in both mindset and architecture. We could even discuss whether it presents a pattern or an anti-pattern since, in a way, it takes the singleton pattern or the (often) hated static variables to the extreme.

In any case, it’s worth taking a look. Libraries like Redux or Vuex are a trend in Web development, and that’s because they are useful and allow for component reuse and independence. Furthermore, they fit perfectly with the use of IoC.