NgRx

A quick tutorial on working with data in an Angular application


Passing data between Angular components can become a nightmare, unless you use a tool like NgRx

Introduction

Angular is a framework for creating the front-end for web applications. However, it is purely geared toward creating visual components, not for handling domain data. That's where NgRx comes in. It's a library for working with data on the front end in a "Flux" pattern, which is a slight variant of MVC (I like this explanation of it: Flux vs MVC). All modern web frameworks have a typical library like this for handling data. For React, the library is Redux. For Vue, it's Vuex.

Some quick terminology:

In a nutshell, using NgRx will look like this:

  1. import the store at root
  2. create a reducer for defining and changing state
  3. import the store and any reducers in your component
  4. use your reducer by dispatching actions to it
  5. subscribe to the store to detect when data is changed

What This Tutorial Covers

What This Tutorial Covers
  1. Installation / Set Up
  2. Reducers & Actions
  3. Dispatching Actions
  4. Subscribing
  5. Testing

What You Need For This Tutorial

What You Need For This Tutorial

Nothing unless you want to experiment, in which case: a Angular playground with NgRx


NgRx Set Up

You install the library with:


npm i --save @ngrx/store
      

To enable NgRx, you need to add it to the your app's core module. The value(s) you pass into the forRoot method are the reducers you want to define at the root level, but in this case, we'll just pass in a blank object (reducers are explained later).

Reducers

A reducer is a function that will define and change slices of your entire state.

The reducer receives two parameters, the current state and an action (something you pass in later).

An action has the following structure:


{
  type: 'SOME-ACTION',
  payload: 'some value'
}
      

The type property is a string that will match a switch case in the reducer function. The payload property includes some values (like a string or object with multiple values) that you would like to use to change the state.

Create a reducer (it should be in a directory like so: app/state/domain/domain.reducer.ts):

You can see that the action.type hits a switch statement case, where the state is returned with the mutations you want. You should also know that this is how you initialize state values as well. When the application is first created, all reducers are called, and the default value of state passed to the reducer is used for initialization. Keep in mind though, that this is the default value and not the property. You set the property name in the following step, when you import the reducer and pass it to the store module's forFeature method.

Component Set Up & Dispatching Actions

To use the store in a component, you must add the NgRx module to the component's module along with whatever reducers you want to use:

Now, in your component's code, you can change your state by calling the dispatch method on your store.

Subscribing

Other components can subscribe to changes in your state. Import the module and reducers into the component like the previous step. Then, subscribing is as simple as using the select function to select the property you want to observe and the subscribe method subscribe to changes:

Testing

Testing basically involves importing the the store module using both forRoot & forFeature, and then combining the reducers that are imported. At that point, you can use your store in your unit test. To see a full example, go the following official link:

NgRx Store Testing: Read Me

Dev Tools

There's a great extension for Chrome where you can see what your state looks like, as well as previous states, in Chrome's developer tools window.

To use it, you first have to add and enable an npm package on your project:


npm i --save @ngrx/store-devtools
      

To enable the package, add it to your application's root module. The check for environment.production is a flag you can use to omit the tool when building your application for production.

Finally, add the Chrome extension by going to the following link and installing it (although it's called "Redux DevTools", as in the tool used with React, it works with Angular/NgRx as well (as they both use the Flux model):

Redux DevTools

Now, you should see an icon for the Redux DevTools that looks like 3 concentric circles (like a diagram of a solar system or an atom). It should light up when you visit your application. Clicking on it will give you data about the state. You can also click on the "Redux" tab inside of Chrome's developer tools to get more info.

Done!

So that's how you handle state with modern frameworks like Angular.