Apps need to manage state and react to state changes in order to provide an engaging user experience.
State Management is a deep topic, and the sheer volume of libraries and approaches can be overhwelming. We'd like to document some of the most popular state management solutions used in the Ionic ecosystem and some things to think about when looking for a state management library.
In the Angular world, there are two leading state management libraries we see teams adopting: NgRx and NGXS. Both are a fine choice and will come down to preferences around code structure and boilerplate. Both are modelled on redux, and will require defining, dispatching, and handling actions.
Two other options worth considering:
- Akita which does not require the typical boilerplate used in redux and may be a better fit for smaller applications.
- MobX which is a popular library with support for many frameworks. Its approach is unique and could be a good fit for small-to-medium sized applications
One of the great benefits in using a state management library in Angular is being able to move to using Angular's
OnPush change detection strategy which improves performance.
The React ecosystem pioneered a number of state management approaches, including Redux. Due in part to this environment of innovation, there's a plethora of options for state management that developers can pick from.
We have a few favorites. Some of these may be familiar but a few of them might not be.
- React Redux - the original Redux state management library for React. Strongly embraces the classic Redux approach. We find this library works fine for medium to large apps, but the boilerplate can become very unwieldy without careful planning. Often used with redux-thunk or redux-saga to manage side effects or app actions.
- MobX - as mentioned above, MobX is popular in the React ecosystem and takes a unique approach that greatly simplifies state management.
- Recoil - built by developers at Facebook, Recoil is a relatively simple state management library good for small to medium-sized apps.
- Zustand - the simplest popular option on this list. Works great with React Hooks and requires the absolute minimum to get started.
The above are the most popular options in the ecosystem, but there are a few more worth mentioning:
- Pullstate - Pullstate is a favorite of some of the developers at Ionic because it's very simple, requires the absolute minimum amount of boilerplate, and is fast. Likely a good fit for small apps.
- Akita - Akita, as mentioned above for Angular, also supports React and is worth considering
In our opinion
When it comes to state management, Redux is king. As one of the pioneers of state management approaches, Redux is popular due to its suitability for large applications, flexibility, and deep integration into popular frameworks like React. Because of that, it might be tempting to just pick Redux and a supporting library for your framework, but it is worth considering other options.
One of the biggest challenges with Redux is the overhead in using it as the codebase grows. Every action the application supports will be defined and fully typed, and actions need to be handled in a way that can be quite verbose. This leads to bloat and engineer fatigue as the codebase grows. Take it from us, we've seen this in our own internal apps and in customers apps, and it can seriously slow down progress and lead to a lot of superfluous work.
Much of this can be avoided if proper steps are taken. For example, in React, using Redux Saga can cut down on complexity at the expense of a more opinionated programming model. In Angular, redux libraries are able to take advantage of Angular's object-oriented approach and tooling to further cut down on complexity as a codebase grows.
While Redux can be tamed, I would encourage teams to consider a non-Redux state management library if their app will stay relatively small or even medium sized. I'm personally a big fan of libraries like Pullstate for React which don't require developers to type or define any kind of actions and have deep integration into state/change detection in your framework of choice. Using Pullstate and libraries like it requires a small layer of extra code but provides great performance and reactivity.