Why NgRx is a great choice for State Management.
Actively Maintained - NgRx is actively maintained and keeps evolving with Angular.
Great Documentation - NgRx documentation is great and @ngrx/eslint-plugin can help you follow NgRx’s best practices.
PRO TIP: if you use @bitovi/eslint-config, there’s no need to worry: NgRx recommended ESLint rules will be configured for you.
Maintainability - While NgRx allegedly has a lot of boilerplate code, NgRx does help keep your code tidy!
Performance - NgRx is carefully implemented with performance in mind, and it complements the Angular Ecosystem perfectly because of its Reactive approach.
Understanding the Key Concepts of NgRx
The Redux pattern manages the Global State of an application and aims at code testability and predictability.
Redux is known for its boilerplate code. At first, it might seem like a lot of effort to implement Redux, but in fact it is a tradeoff. Redux adds a layer of indirection in order to improve maintainability, testability and predictability of your application. The tradeoff pays off more often than not particularly if your application is complex, large and maintained by a large team.
Redux expects updates to the state to be done immutably. Not only does Immutability help Redux implement patterns that increase testability and predictability, it also improves performance, as change detection is achieved with less effort.
A Store is an object that wraps the state. The Store also provides helper functions to update the state and listen to state changes.
Actions are objects that represent individual events in your application.
Actions are created using two properties:
type- Describes the event.
payload(optional) - Holds additional information.
Actions are necessary to update the state by triggering Reducers.
To put it simply, Reducers are
pure functions that take the state and an Action as arguments, and return a new state. In other words, Reducers are functions that, given an Action, know how to update the state.
Reducers functions must be
do not depend on any information other than the Action and current state.
do not perform side-effects, like mutating the current state. When using NgRx, side-effects are already handled through Effects.
A Dispatch is a
Store method that will provide an Action to the Reducer function. You can see the
dispatch() method as the API to update the state. Effects also listen for every Action dispatched from the Store to handle side-effects.
Selectors are functions that extract data from the state. Selectors can return derived data or slices of the state.
One-way Data Flow
To help you understand how Redux pieces work together, let’s take a look at the most basic representation of how data is passed around in an application that uses Redux, also known as a one-way data flow, taken from the Redux Official Documentation.
Data goes through the following steps:
reducerfunction takes the
actiontype and payload and current
stateto return a new
view, which is subscribed to
selectors, triggers a re-render of the
viewbased on the new
NgRx State Management Lifecycle
NgRx abstracts away from one-way data flow to represent its own Store implementation pieces and interaction with external entities, such as Components and Services, to what is referred to as the State Management Lifecycle.
We’ve mentioned side-effects before: Reducer functions must be pure and not perform side-effects. While the Redux pattern suggests that side-effects should be performed as part of the Action creation process, NgRx’s solution - Effects - is a more reactive approach.
In NgRx, Effects will:
Listen to an
action$Observable and filter the Action(s) relevant to the Effects.
Perform side-effects and return a new Action. If there’s no need to update the state or trigger other Effects, an Effect may not return a new Action (Non-dispatching Effect).
Note that for a given Action, Effects will always happen after the state has been updated by the Reducer.
Now that we’ve taken a good look at the bigger picture, let’s dive in and set our environment up so we can get our hands dirty with some coding!