Language: EN

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

Redux.NET, a state container for .NET applications

Redux.NET is a predictable state container for .NET applications based on the development of Redux 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 such as 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 the components of an application.

When we develop an application in MVVM, one of the first normal concerns is how to exchange information between the components of an application, keeping the coupling between classes weak.

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

Redux.NET is an alternative or complement to these methodologies. According to the Redux philosophy, the state container is “predictable” as 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 done 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 in the Store./li>
  • 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 of them, the ‘Counter’ example that simply contains a counter that increases or decreases its value.

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

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
  }
}

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

public class IncrementAction : IAction { }

public class DecrementAction : IAction { }

The necessary Reducer is also defined, which defines the next state based on the current state and the received action. In this example, simply the new state is to increment/decrement 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;
  }
}

With all this defined, now we will 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 actions defined previously.

On the other hand, in the constructor, we subscribe to the 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());
  }
}

It is a very simple example but it allows us to introduce the three fundamental elements (Store, Actions, and Reducers). It is easy to extrapolate this example to a real project, where the Store would have a more complex object that would contain the necessary variables to represent the state of the application.

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

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

Redux.NET is Open Source and its code is available on Github at https://github.com/GuillaumeSalles/redux.NET. It is compatible with .NET Standard, and you can easily add it to your application through a Nuget package.