Angular - NGRX A Clean and Clear Introduction - Frontend Fun - Medium
Angular - NGRX A Clean and Clear Introduction - Frontend Fun - Medium
The objective of this article is to provide a clean and clear introduction to ngrx. In order to
accomplish this, I am going to explain the things you need to know and understand about ngrx
and then we are going to see it in action with some simple and understandable code examples.
Finally, I am going to provide the link to the GitHub repo containing the examples so you can play
around with the code.
This is the list of topics that we are going to discuss in this article:
What is ngrx
Benefits of using ngrx
Cons of using ngrx
When to use ngrx
Actions, Reducers, Selectors, Store, and Effects
NGRX example
What is NGRX
NGRX is a group of libraries “inspired” by the Redux pattern which in turn is “inspired” by the Flux
pattern. Being a little more concise, this means that redux pattern is a simplified version of the
Flux pattern and NGRX is an angular/rxjs version of the redux pattern.
What do I mean with “angular/rxjs” version of redux… The “angular” part is because ngrx is a
library to use within an angular application. The “rxjs” part is because the implementation of ngrx
works around a rxjs flow. This means that it works using observables and the different observable
operators provided by “rxjs”.
The main purpose of this pattern is to provide a predictable state container, based on three
main principles.
Let’s go through the three principles of the Redux pattern and point out the most important
benefits they provide.
Within a single store? We are going to talk later about stores, but in a general definition, they have
the responsibility of holding the state and applying changes to it when they are told to do so (when
an action is dispatched, we are also going to talk about them later).
The benefits of having a single source of truth are plenty, but for me, the most interesting one
(because is the one that is going to impact on any angular app) is the following:
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 1/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
When you are building an angular app usually you have the state split and handle in
multiple services. As your app growth keeping track of your state changes starts to get
messy and hard to debug and maintain. Having a single source of truth resolves this
problem since the state is handled only in one object and in one place, so debugging or
adding changes becomes way easier.
State is read-only
You are never going to change the state directly instead you are going to dispatch actions. These
actions describe what’s happening (can be things like getting, adding, removing, updating the
state).
Dispatch an action?… We are going to talk about actions later but for a general point of view, they
are identifiers of an operation on your application and they can be triggered (or dispatched) to tell
the application to execute the operation that the action represents.
By avoiding to update the state from different places and having a centralized place to make
changes, that responds to specific actions, you get a lot of benefits. Just to mention the most
important ones:
You know that any change to the state is going to happen only in one place. This has a
great impact on debugging and testing.
You know that if a certain action is dispatched the operation in the state is always the same.
Again this impacts directly in debugging and testing.
These reducers (remember that they are just pure functions) receive an action and the state,
depending on the action dispatched (usually with a switch statement) they execute an operation
and return a new state object.
State in a redux app is immutable! So when a reducer changes something in the state, it returns a
new state object.
The benefits of using pure functions are well known, like the fact that they are immediately
testable if you pass the same arguments you are going to get the same result.
This approach also allows us to navigate between different instances of our state using
Redux/ngrx dev tools and see what changed between instances and who change it, among other
things. So using pure functions and returning new instances of the state has also a great impact
on debugging.
But the main benefit, in my opinion, is that by binding all our components inputs to state
properties we can change the change detection strategy to on push, and this is going to
be a boost on performance for the application.
We have already mentioned most of them out while talking about the redux pattern principles. But
let’s point out the most important benefits of using the redux pattern in an application (in my
opinion):
Since we have a single source of truth and you can’t directly change the state, applications
are going to behave more consistently.
Using the redux pattern gives us a lot of cool features to make debugging easier.
Applications become easier to test since we are introducing pure functions to handle
changes in the state and also because both, ngrx and rxjs, have a lot’s great features for
testing.
As soon as you feel comfortable with using ngrx, understanding the flow of data in your
applications becomes incredibly easy and predictable.
I do agree that it should be considered to be used in medium or big projects when you have a
considerable state and a bunch of components using this state but you have to consider that
Angular by itself provides plenty of solutions for managing the state and if you have a strong front-
end angular team, then maybe you don’t need to bother about ngrx.
That being said I consider that a strong Angular team may also decide to include ngrx to the
solution because they know all the power of the redux pattern and also the power added by rxjs
operators, and they feel comfortable working with both…
If you were expecting a simple answer to decide when to use ngrx, you are not going to obtain it,
and don’t trust anyone giving you this answer from outside your organization or team. The decision
depends on studying the pros and cons, understanding your team and considering their opinion.
In the image, we can see the ngrx flow. Let’s explain it…
1. In the most common scenario, everything starts in the component view. Some interaction made
by a user may cause the component to dispatch an action.
Actions…
In the store object, you have a function to dispatch (trigger) actions. Actions are classes that
implemenets the NGRX Action interface. These Action classes have two properties (let's take as an
example an action class called GetUserName):
type: it’s a read only string describing what the action stand for. For example: ‘[User] Get User
Name’
payload: the type of this property depends on what type of data this action needs to send to the
reducer. In the case of the previous example, is going to be a string containing the user name. Not all
actions needs a payload.
2.1. If this action doesn't trigger an effect then a reducer is going to analyze the action (usually
using a switch statement) and return a new state that’s is going to be the result of merging the old
state with the value that changed by calling the action.
Reducers…
Reducers are pure functions accepting two arguments, the previous state and an Action. When an
Action is dispatched ngrx goes through all the reducers passing as arguments the previous state and
the Action, in the order that the reducers where created, until it finds a case for that action.
2.2. If an effect gets triggered by dispatching an action is because some side effects are
going to happen before calling the reducer. This can probably be something like calling an
HTTP service to get data.
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 4/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
Effects…
Effects, on the ngrx libraries ecosystem, allow us to deal with side-effects caused from dispatching
an action outside angular components or the ngrx store.
The Effects listen if any action is dispatched, then, similar to what reducers do, it checks if the action
is one of the actions type it has a case for.
Then is going to perform a side-effect, usually getting or sending data to an API.
Finally is going to emit another action, usually, an action referring to the result-state of the side
effect (success, error, etc), then a reducer is going to enter in the scene as we already mention in the
ngrx flow.
2.2.1. After the effect is done (side effects are finished) a new “state-result” action gets
fired by the effect (it can be that the side effects succeeded or failed), and we are back to point
2.1.
3. Now the Store has a new state. The state can be a big object tree, so ngrx introduces
selectors to be able to use only the slices of the object that we need in a specific
component.
Selectors…
As we mentioned before the state tree can become quite a big object, it doesn’t make sense to have
all that object on places where we only need part of it.
NGRX store provides us the function “select” to obtain slices of our store. But what if we need to
apply some logic to that slice before using the data in the components.
There is where selectors take action. They allow us to decouple any state slice data transformation
from the components. The store “select” function accepts an an argument a pure function, this pure
function is our selector.
Store…
A store is an object (an instance of the ngrx Store class) that brings the things we mentioned before
(Actions, Reducers, Selectors) together. For example, when an action is dispatched (using the store
object dispatch function), the store is the one finding and executing the appropriate reducer.
NGRX example
Great… so we are done with the what, the why, the when and introducing the flow and actors of
ngrx, now is time to see it in action. This could easily be another article, but in my head, it makes
no sense to explain all of the things we have explained without a code example where we can
see everything in action and that you can download in order to play around with it.
Our example is going to have a list of users, the user detail page and some initial configuration
information that you need to get when the app starts. We are going to be able to implement some
important ngrx flows.
So let’s do it…
We are installing almost all the libraries of the ngrx ecosystem. Most of them are quite clear about
their purpose like core, store, effects, but there are a couple that you may wonder what they are
for.
As we mentioned before, we are going to have two main sections on our application, users, and
configuration. For both of them, we need to create the state and the initial state, and we also need
to do the same for the app state.
We created two interfaces to define user and config. We also have one for the user HTTP
response, that is just an array of IUser.
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 7/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
1. The application state contains the user and config state, and also has the router state.
2. Then it has an initial application state.
3. Finally, exports a function to get the initial state (we are going to use it later).
Create Actions
Be sure you read the Action definition that we discussed in this article.
We need to create the actions for users and configuration. Let’s start with the user's actions
(store/actions/user.actions.ts):
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 8/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
So this is a good example of actions being created for a feature or entity in our application. Let’s
go through the code a little bit:
1. We export an Enum containing the definition for the actions types. In this way, we avoid
using and repeating strings to use the action types, a process that can easily deriver in
errors.
2. We create and export a class for each of your actions. All of them have to implement the
Action interface from ngrx. Finally, we set the type to one of the enums values and if you
need a payload for the action you add it to the constructor of the class.
3. Finally, we export a type containing our action classes. This is going to provide us with type
checking that we can use for example in our reducers.
And that’s it… creating actions is simple. Let’s take a look at how the config actions look
(store/actions/config.actions.ts):
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 9/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
Nothing new here, you probably now feel comfortable with everything going on this file.
Great, we have already defined the state and the actions… let’s create the reducers!
Create Reducers
Be sure you read the Reducers definition that we discussed in this article.
We are going to have reducers responding to some of the actions because others are going to be
handled by Effects that we are going to implement later.
We are going to need a reducer for users and other for the config but we are also going to need
to generate app reducers, let’s start taking a look to the user reducers
(store/reducers/user.reducers.ts):
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 10/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
1. The declaration of the reducer receive the state and, in this case, the user actions and
returns an IUserState.
2. Using a switch statement we generate cases for each possible action type.
3. Each case returns a new object that is the result of merging the old state and the new
value.
4. All reducers have a default result that just returns the state without any changes.
And this is it. You are not going to find anything different to this inside a reducer. Let’s take a look
at the config reducers (state/reducers/config.reducers.ts):
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 11/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
Looking at that code you probably already feel comfortable with what you see, we already
discussed everything that’s going on in that file.
Here is where we add all the reducers to an app action reducer map. We use the action reducer
map for added type checking. Later we are going to provide this app reducers to the store
module.
Great!… now we have our state, our actions, our reducers, we still need the effects and the
selectors. Let’s add our Effects…
Create Effects
Be sure you read the Effects definition that we discussed in this article.
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 12/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
You probably already notice that in the reducers we are not handling all the actions that we have
created. This is because we are going to handle the missing actions in effects because these
actions have side effects.
We have many things happening in this file. Let’s try to explain them:
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 13/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
This is pretty much the same structure that you are going to see on any effect. In this case, we
are only dispatching a success action but we could be dispatching errors or any other kind of
state that we want to handle in our application reducers.
Again, you probably feel comfortable by now with the code above.
Create Selectors
Be sure you read the Selectors definition that we discussed in this article.
It makes no sense to repeat selections of slices of our state all over the place, so let’s create
some selectors that we can re-use.
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 14/19
Like always let’s see first the user selectors (store/selectors/user.selectors.ts):
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
This is really clear because we are not doing any data transformation in our selectors, instead, we
are just returning the slice of the store that the selector refers to using the function createSelector
of ngrx/store.
The first param is the slice of the store that is going to use to get the data from (it can be an array
with multiple parts of the state), the second param is the anonymous function that is going to
resolve what the selector is going to return.
And that’s how you create selectors. Let’s take a look at the config selectors
(store/selectors/config.selectors.ts):
Like it happened before, you already feel comfortable with this code.
We have already created all the things we need for the store, but we need to put all of this
together. For that let’s take a look at the next section.
Setting everything up
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 15/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
Great so we created all the things our store needs, but we have one thing missing yet, putting
everything together. I am going to do it in the app module, but you can apply the same in the core
module of your app.
1. We import our reducers and we provide them to the forRoot of the store module.
2. We import our effects and we provide them inside an array to the forRoot of the effects
module.
3. We set the configuration for the router state module providing the stateKey router.
4. And we add the store dev tools if the environment is not production.
The first two steps are necessary while the steps 3 and 4 I highly recommend them but they are
not mandatory.
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 16/19
Now we are finally done… we can use our store in our components!
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
Great Santi, I spend 20 minutes reading your article, I know what I need to know about ngrx: what is
it, when to use it, how to set it up… and that’s awesome, but can you please show me now how I use
it!
Yes, I can! Please don’t lose it yet, we are getting to the end! Let’s see how to use our store…
That’s it… We already code the effect that is going to handle that action and the reducer that is
going to handle the success of that effect. As soon as the Store has its new state the selector is
going to change the value on our property. Amazing!
I am using the concepts of containers components and presentation components. If you are not
familiar with this approach, take a look here.
1. Similar to how we manage the config we are going to get the user list. First, we inject the
store into the user's component.
2. On the onInit we dispatch the action the get the users.
3. We create a property on the component and we assign it the user list using the user list
selector.
We render the user list in the presentation component sending the list and binding the select user
to a navigation function that we can see in the user's container component above.
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 18/19
9/4/2019 Angular: NGRX a clean and clear Introduction - Frontend Fun - Medium
This component gets the param id from the activated route, and for the rest you are probably
already familiarized with, dispatching sending the id as param, selecting the selected user…
If you want to see all the code just go to the GitHub repo.
If you debug the application you can see the developers tools, that are quite simple to use… but
we went through enough in this article and I trust you are going to get your head around those
tools without any problem.
Conclusions
In this article, I tried to deliver a clear and clean ngrx introduction by providing you with all you
need to know to enter this world.
We started explaining concepts, understanding how it works, why to use it and finally, we went
through a complete basic example.
https://medium.com/frontend-fun/angular-ngrx-a-clean-and-clear-introduction-4ed61c89c1fc 19/19