Implementing state management in an Angular complex app

Iker Bedecarrax
Shippeo Tech Blog
Published in
6 min readOct 27, 2022

This article explains what is a state manager, how does it work and why should complex applications use it. Here we will focus on Angular frontend complex applications as we will give an overview on the most famous state management solutions in Angular.

Context

State management ? 🤔

Nowadays, modern web applications are single pages composed of dynamic web components. Application components are conditionally displayed in the view regarding user’s permissions and navigation. Moreover they adapt their own rendering related to their specific data. The data linked to a component that defines its rendering is then called a state.

Then the state management is basically the management of all data states within an application.

Avoid the mess 🤯🧹

State management can quickly become a big issue if developers do not have scalability in mind as the application grows.

In small applications, component states can be accessed and modified internally. However, the complexity increases with data sharing between components. In large applications, components often manipulate and share the same data sources by reference, and you can easily lose the current data state.

As the application grows, the number of states grows as well and become more complex as well. They might be accessed from plenty of components or controls among several libraries. At this point, the management of the states becomes a hassle to maintain.

A good SM recipe 👨‍🍳

A recipe for a good state management should at least gather the three following ingredients:

  • Performance: Actions on state have to be asynchronous as the action queue asked by components does not lead to performance leaks
  • Consistency: is fundamental to make all components share the same data state at every moment
  • Visibility: Each data update has to be noticed to let developers time travel through these changes and debug easily

Solutions💡

Patterns

Observer design pattern

With the power of observer pattern, we can define shared data as observables where a modification made by one component on a specific observable updates all components that observe the succession of events emitted by this observable. Such components are called observers and the succession of events is simply the succession of data states.

This solution brings asynchronism and guarantees performances while scaling.

Reducers

Based on Redux library for React, a reducer is a state manager that provides a single Store to held the global application state as an object tree. Whenever the store is updated, it will update the components subscribed to it.

A reducer also let developers define Actions that are static information about the event that initiate a state change. Actions are linked to pure reducer functions in order to mutate the state. A reducer function will consider the previous state and action as parameters, and return the application state.

Learn more about Redux

Implementations in Angular

Rxjs

Angular needs the help of Rxjs to implement the Observer pattern and solve multi directional data access and modification issues.

It is possible to manage multiple states using only Rxjs by reproducing based on a Subject the Actions and the Selectors that a reducer library provides. But this custom way might be messy to manage in large applications due to the lack of visibility and the complexity to debug.

NgRx / Ngxs / Akita

In large applications, centralize states into one single application store can be very powerful and enhance scalability. Three main Angular libraries implement reduce state management to achieve this goal :

  • NgRx: This is the original state management library for Angular and remains the most exhaustive and customizable solution. Consequently it needs a big boilerplate to use it. As the leading solution, it brings lot of dedicated tools and a great community.
  • Ngxs: Ngxs is the second famous solution to manage states in Angular. As it is more recent than NgRx, it is based on modern Typescript features that let reduce boilerplate.
  • Akita: Akita is newer than the other solutions and is more common in smaller applications as it is light and encourages simplicity with small boilerplate.

Choose a reducer

Benchmarks of Angular reducers

A helpful article shows up benchmarks for these solutions that we can analyse thinking about our application :

The choice of Shippeo

  1. First, as our application is vast and complex, we need the most customizable solution with great tools and features package, that is why we won’t choose Akira.
  2. Then, Ngrx is for now the only solution supported by Nx that we use as project manager. Using Ngrx will let us take advantage of Nx powerful machinery as schematics and upgrade automatization.

As a result, we decided in consortium to choose Ngrx that seems the best to fit our specific needs.

Summary

  • State management becomes necessary as the application grows and increases its complexity. We avoid the mess accessing components data and maintain performance in scalability.
  • Angular already uses the capabilities of the observer pattern provided by Rxjs library giving us access to Subject and Observable flows
  • Ngrx is an Angular state management solution based on Redux pattern paired with Rxjs. We basically chose this solution among the others because it is the most complete and the only one supported by Nx until now.

Sources

--

--