05 November 2019
Angular state management with Redux Pattern
State management is a very important part of web development. Sharing data between different components (especially with many separated ones) can be really difficult. Also, it ain’t easy to debug it when something goes wrong. Nowadays, we have so many libraries for state management, that it’s pretty tough to choose the right one. That’s why, in the article, we’ll try to present you all the available options to help you understand what is state management in Angular. It can help you choose the best solution for your case.
If you ever had anything to do with Angular web development services – most probably you know that sometimes, it can be really messy and complicated. No matter how experienced you are – web development can take you by surprise. That’s why it’s good to be prepared for any circumstances and start with…
Simplifying the process
Once it’s pretty difficult to choose the right library for state management – on the other hand, it’s really easy to find yourself in not-that-optimal-situation when unnecessary complexity of the system appears or there’s too much boiler code. That’s why it’s so crucial to choose the right approach.
Flux is an architecture pattern created by Facebook to resolve their problems with Messenger and the information related to it. For example information about how many unread messages you have, used to be displayed in many places and that was causing some problems with refreshing proper views.
Flux pattern forces data to flow in a single direction. A component can change application shared data only by executing an action. This should help to have state management in one place. It should simplify the process. Diagrams below explain it pretty well.
Let’s start with a short presentation of the libraries that we will compare today. It can help you understand different approaches of managing state of your Angular app.
📗 State of Frontend 2020
Report on frontend development trends based on the opinions of 4.500 developers. 🚀
NGRX, NGXS and angular-redux
- NGRX
NGRX is powered by RxJS, inspired by Redux. It requires lots of boilerplates and it has a steep learning curve.
- NGXS
NGXS is modeled after the CQRS like in Redux. However, it reduces boilerplates by providing strong typing, using modern TypeScript features (such as classes and decorators).
- angular-redux
angular-redux provides Angular bindings for Redux which helps you integrate your Redux store into your Angular applications. It fills the gaps with some of Angular’s advanced features, including a change detector. Also, it compiles time optimization (AOT) and processing with RxJS.
Now, we will compare those three libraries. We will check a few aspects like features, development tools, package size and community. Let’s go!
Main features, tools and community
- Features
- Selectors – functions or decorators for getting out a part of the store.
- NGRX – contains optimized functions for selection. It offers memoization which can return the last result if you call a function with the same arguments. You can compose function for more complicated selectors.
- NGXS – gives you two options to read the store. You can call the
select
function on the store or use select decorator@Select
. You can use@Selector
for a more complex function which will memoize the function, but you need to do in a class responsible for a given part of the state, not in a component. Once you create it, you can pass your@Selector
functions into@Select
decorator to use it in a component. - angular-redux – you have also
@Select
decorator. You can pass a string, an array of string or a function as a parameter. Alternatively, it can be left empty. In that case, the selector will try to match part of the store using a property name. You also have aselect
function.
- Async Actions – these allow developers reducing a state asynchronously.
- NGRX can handle async actions with
@ngrx/effects
, a separate package needs to be installed. They can react not only to emitted actions but on any Observable. Also, they must emit a minimum of one new action. You can emit more actions if you need though. - NGXS allows actions to be handled asynchronously, just out-of-the-box. Async actions can dispatch different actions, but not only. They can also modify the state directly. It’s important that they must return an Observable or Promise to notify the dispatcher that the action has been completed.
- angular-redux – actions in Redux are dispatched synchronously by default. That’s why a separate package must be installed to handle async actions. You can use redux-thunk or redux-saga for example, but we highly recommend using redux-observable. It’s connected with RxJS which you already have in the project because of Angular requirements.
- NGRX can handle async actions with
- Meta reducers – allow developers to pre-process actions before normal reducers are invoked. Simply – it’s a higher order reducer which returns another reducer.
- NGRX allows composing an array of meta reducers by configuration option for
StoreModule
.They are composed from right to left and in the life cycle, they work similarly to Redux middlewares. - NGXS does not have a concept of meta-reducers, but you can easily implement it by using NGXS plugins. Plugins can manage a whole state because they have access to state and they can handle dispatched action.
- angular-redux can have meta reducers through creating a reducer as a higher order function which returns another reducer.
- NGRX allows composing an array of meta reducers by configuration option for
- Selectors – functions or decorators for getting out a part of the store.
The frameworks offer more features which are included on the summary table below.
- Dev Tools
NGRX provides @ngrx/store-devtools
for DevTools. It works as expected, displaying the latest actions with their impact and the resulting state of the store. It’s possible to jump to specific actions and even skip actions. It also allows devs to dispatch an action directly from the DevTools. However, it does not verify that action’s payload.
NGXS provides @ngxs/devtools-plugin
for DevTools. It does not support all functionalities though. The latest actions can be viewed with their impact and resulting state. While it’s possible to jump to specific actions, it’s not possible to skip actions or dispatch new ones using the DevTools.
With angular-redux you can use DevToolsExtension which is an Angular binding for redux-devtools-extension and it’s a part of @angular-redux/store
package.
- Size – minified + GZIPPED
We only compared the core store package with built-in features. NGXS has the biggest amount of features built-in and you can notice it when looking for its size. The final size depends on installed packages for features that are missing in the core package but are required for your project. That’s why it’s difficult to compare how big it can be eventually.
@ngrx/store – 5.1kB
(details)
@ngxs/store – 8.2kB
(details)
@angular-redux/store – 3kB
(details)
- Community
NGRX is the most popular package for state management in Angular. It has twice as many stars on GitHub as NGXS. Same for NPM statistics.
There are no problems with finding information and robust documentation for any of these packages (NGRX, NGXS or angular-redux). Additionally, for angular-redux, you can use the wisdom of the Redux community.
See also: Let’s review the latest changes in all of the most recent Angular versions 👇
Summary
So what should you use? Which one is a golden package and cure for a state management hell? Yes, you’re right – it depends. 😄 We used each of those packages in different projects and we have seen the most terrible and almost perfect usage of each one.
We think that NGRX is the most difficult and complicated one. It forced us to write a lot of boilerplates. Also, more code equals more space to make mistakes and the easiest way to make code more difficult to understand. Believe us, making things difficult is very easy with NGRX.
- NGXS is a bit simpler and has a lot of things covered by default or an additional package from the same author. It’s a huge advantage because when it depends on many different authors from separate repositories, it’s easy to get unsynchronized and get a lack of support for new versions.
- Angular-redux is the simplest one. That’s why we think it’s enough for most cases. It should be used by people with experience in Redux who don’t feel confident with RxJS or just don’t want to experiment with NGXS. If you already used Redux with React then make sure to go for angular-redux.