NGRX Store in Angular is a global state management solution inspired by Redux. It claims to help write performant, scalable, and consistent applications, but does it deliver on that premise?
Why do we need the NGRX Store in Angular?
Let’s take a step back and think about what problem an NGRX Store solves.
When components from different hierarchical levels need data from each other just in order to pass that data to child components, so-called “extraneous props”. In terms of Angular, it’s @Input properties of the components that are not used directly by the component and just passed to children components. Another problem is emitting events several levels up in the hierarchy just to handle the event in top-level components.
In a nutshell, the NGRX store solves the problem of component communication at multiple disconnected places of the component hierarchy.
Price for using NGRX Store
You have to pay the piper. The price for using the NGRX for state management is high:
- A lot of boilerplate code when you need to create a bunch of files for every change, such as state model changes, reducers, actions, and selectors. That’s very cumbersome. The codebase becomes bloated with all of this “infrastructure code”.
- Using RxJs with NGRX Store overcomplicates the code and you end up with lots of obscure (for unprepared developers) “reactive magic”.
- A steep learning curve means that it’s harder to introduce new developers, and without understanding functional reactive programming and the RxJS library they tend to make lots of mistakes.
- There are no clear guidelines regarding using NgRx Store. Some developers keep everything in the state and do everything through the store for consistency. Other developers argue that only global data used by multiple components should be stored in the state.
- It’s hard to have both a regular angular way to do things (more on that later) and an NGRX way in the same app. You can’t mix it and easily add NGRX to the already existing project. Otherwise, you will end up with code where there are multiple ways to add new functionality and developers will be confused every time they need to deliver new features.
So using NGRX Store on our project led to the following problems:
- Lots of boilerplate and bloated code;
- Lack of FRP understanding among developers resulted in error-prone code;
- Slower delivery of new features;
- Lots of controversial architectural debates.
I don’t claim that these problems are going to be in every project with NGRX, but it just creates more problems than it solves.
So why you don’t need the NGRX store?
I like Angular because it’s a very opinionated framework with clear guidelines and best practices and usually only one right way to do things. It’s a full-featured framework that already has everything built in.
And for component interaction and sharing state between components, we have a number of ways:
- Services with Subjects that hold a shared state and are injected into components on any level of the hierarchy.
- Passing data from parent components to the child with Input bindings.
- Emitting events from child components with EventEmitter and listening to these events in the parent component.
- Injecting the child component into the parent as a ViewChild.
And that’s not even all possible ways, you can read more in the official docs.
NGRX Store can be a good approach in some rare cases, but chances are you don’t really need it and it’s better to follow the Angular way.