When working with large or complex applications with a lot of asynchronous activity and where there’s a lot of state that is being shared and manipulated between multiple components and modules, managing state quite can be challenging. In a typical application, a state can be like any,

  • Information about the view, such as whether to display a specific fields or UI elements
  • Data that comes through API calls and whether it is pending or resulted in an error
  • User input, such as currently selected item, form submissions, search query results and filters or any other information or data that the application tracks.
  • Many other types of state.

As the application grows, to handle state change consistently and accurately in between modules and components we really need a state management pattern for the application. Otherwise, it becomes extremely difficult to find out the reason about what’s actually happening in your application. So, here Angular has come up with Ngrx(@ngrx/store).

What is Ngrx?

Adds redux pattern with RxJs inbuilt support to Angular

ngrx

Ngrx(Reactive Extensions for Angular) is a set of RxJs powered state management libraries for angular applications which is inspired by Redux, a popular and predictable state management container for javascript applications.

The purpose of Ngrx is to provide a formal pattern for

  • Organising our application’s state into one single, local state container
  • Managing that state by requiring a one-way data flow (Unidirectional data flow)
  • Communicating state changes to the components to react accordingly.

As shown in the image above, Ngrx is being inspired by Redux, and it imports all core concepts from redux and supercharges it with RxJS.

What is Redux?

Redux is a predictable state container for javascript applications.

As stated earlier, Redux is a state manager for javascript applications. It implements core ideas of flux design pattern (developed by Facebook) by having one-data flow (unidirectional data flow) in your application.
Where flux applications traditionally have multiple stores but Redux has only one single store that contains the state for the entire application.
The whole state can be stored in one object tree that is accessible from every component of the application and the components listen to the data in a store that they are interested in.

The three Principles of Redux:

Take a look at the three principles of Redux pattern before diving into the “@ngrx/store“.

  • Single source of truth(Store): The state of the application should be stored in a single store. The store is the responsible for providing data to the components.
  • State is read-only: The state is read-only or Immutable that means if you want to update the state, new action should be emitted.
  • Pure function reducers: Reducers are pure functions that takes a previous state and an action, and return a new state. They don’t modify the existing state, instead they return a new one.

What is Rxjs:

RxJS (Reactive Extensions for JavaScript) is a library for reactive programming using observables that makes it easier to compose asynchronous or callback-based code.

Observables is a new primitive type which acts as a blueprint for how we want to create streams, subscribe to them, react to new values, and combine streams together to build new ones.

RxJs plays well with Angular and it also play together very well with NgRx. In fact, RxJs is a dependency in Angular. So, if you’re using Angular, then you’re already using RxJs.

If you want to learn more about RxJs, I suggest you to checkout the below urls.
http://reactivex.io/tutorials.html
https://angular.io/guide/rx-library

Core concepts:

we need to understand a few core concepts before start using Ngrx.

  • Actions
  • Reducers
  • Effects

Actions:

Actions are plain Javascript objects that consisting of a mandatory type property to identify the action and optional information that mutate or change the state of our application.

Here is whats a sample object might look like:

We will use the dispatch() method on the Store to call an action. So, When an action is dispatched, the reducer takes it and applies the payload, depending on the action type, and outputs the new state.

Reducers:

As I stated earlier, Reducers are pure functions that takes the data passed by action and a previous state, and return a new state depending on the action type. They don’t modify the existing state, instead they return a new state.

Here’s an example of sample reducer.

Effects:

So far the actions are intend to mutate the state of our application and reducers() pure functions will mutate the state, but what about performing actual Http Requests to load the data from the api calls. This is where @ngrx/effects comes into play. Effects take an Action, do some work and dispatch a new action.

Ngrx/effects is middleware for handling side effects in ngrx/store. It listens for dispatched actions in an observable stream, performs side effects, and returns new actions either immediately or asynchronously. The returned actions get passed along to the reducer and then reducer will mutate the state.

Here’s is an example of sample effect:

Following is the ngrx/effects diagram that shows the entire Ngrx flow.

ngrx-efffects-flow

Setup Ngrx(@ngrx/store):

We are done with the theory part. Now, lets understand the setup of powerful @ngrx/store.

I have created a working example of an Angular application that uses Ngrx which displays the list of customers, details of each customer and other required actions.

Here, you can find the source code of the application for the reference.
Source Code

Project Structure:

up and running REST API:

In this application, I am using JSON Server to create a fake REST API.

JSON Server is a popular tool for front-end developers for quickly setting up a fully fake REST API in less than a minute. follow the below steps to do the same on your end,

Install json-server via npm

create a sample data in a JSON file inside data directory.
src/data/customers.json

Now, run the server by calling the following command.

Our sample “customers.json” file data will be accessed though the below API.

http://localhost:3000/customers

You can also get other HTTP endpoints (like post, put, and delete..)  that are created automatically by the JSON Server.

To learn more about how JSON Server works, I suggest you to checkout the following URLs.

https://github.com/typicode/json-server
Create A REST API With JSON Server

Now, lets understand the Ngrx Installation and walk-through of the code.

Install the @ngrx modules

State and Models:

First, we will define the application state models
“src/app/models/customer.modal.ts”

“src/app/models/app.state.ts”

Action Types:

Next, define all the action types in a file. We will use these in actions, reducers and effects file.
“src/app/store/action.types.ts”

Actions: 

Next, we will define the Action classes, these are created with the readonly type property. Here constructor function is optional and it is defined when some payload is passed to the Action, which will define the changes to the state.
“src/app/store/customer.actions.ts”

Services: 

Next, we create a service file which will hold all the required api calls. As explained above, we used simple REST Api, provided by the JSON-Server.

Effects: 

Effects take an action, do some work and dispatch new action. Now, we create “src/app/store/customer.effects.ts”  file. 

  • You can register method with Ngrx as an effect by adding ‘@Effect()‘ decorator on top of it.
  • “ofType” does a comparison on Observables. Here it will filter out the actions that we are not interested in except for the action that we are looking.
  • mergeMap over maps every emitted action calling angular services who return observables, then merges these observables into a single stream.
  • Within mergeMap, we are calling a service which either returns a success response or an error.
  • when success response returns, another action is called with response as a payload.
Reducers: 

Now, we need to create a Reducer function that will take State and Action object as arguments and returns a new state based on the action type.
“src/app/store/customer.reducer.ts”

  • Here, Switch generates a state object based on whichever action is called.
  • When LOAD_CUSTOMERS_SUCCESS or DELETE_CUSTOMER_SUCCESS actions are dispatched from the Effect, Reducer create a new state and return that state.
Registering the Store and Effects library:

Now, we need to initialise the Store and Effects library in our root app module.

  • First, we need to import StoreModule, EffectsModuleand StoreDevtoolsModule modules that are provided by Ngrx.
  • We then create the root store by invoking the forRoot() static method on StoreModule. We are configuring the applicationState by registering the CustomerReducer.
  • We then registering effects by invoking forRoot() method on EffectsModule. Here, we will pass array of Effects.
  • We are also going to configure the DevTool instrumentation so we can use the DevTools chrome extension by invoking the StoreDevtoolModule.instrument() static method. Note that we only use the DevTools when our application is not executing in the production environment.
Dispatching an Action: 

Next, we need to dispatch our actions to the Store from our component.
“src/app/components/customers-list/customers-list.compoment.ts”

  • Here, we dispatched two actions to the store to update the state.
  • Here customers$ is an observable that we get from “applicationState” Store.
  • Whenever there is a change to this store, subscribe will trigger the method to update customers data.
  • Then, the customers data will be used in html of the component to display list of customers information.

“src/app/components/customers-list/cusomers-table/customers-table.component.ts”.

Finally, the customers-table component, where you have the customers list html. Here, you can create Input and Output variables to communicate with its parent component.

This child component wont dispatch any actions. This is called a Dumb Component. It will only output the values to It’s parent -The CustomersListComponent. Only the CustomersListComponent will have the knowledge of the store and will dispatch actions.

That’s it, Your NgRx specific classes and methods are wired to the application.

wrapping up: In this article, We have come to know the Ngrx specific modules installation, learned how to define Action, Reducer and Effects and wire them all together. We also learned how to use JSON-Server to handle simple REST Api calls.