Skip to main content

Build Reactive Applications in Angular using NgRx



What is NgRx?

NgRx is a framework for building reactive applications using Angular, which provides state management, isolation of side effects, router bindings etc. that enhance developers experience during the development of different types of applications in it.

What is Reactive Programming?

Reactive programming is a term that you hear a lot these days, but what does it really mean?
Reactive programming is a way to handle events and data flow in your application. In reactive programming, you design your components and other pieces of your software in order to react to those changes instead of asking for changes.
Instead of pushing data directly to the component or service, in reactive programming, it is the component or service that reacts to data changes.

Life-cycle of NgRx


NgRx Life-cycle Flow Diagram
NgRx Life-cycle Flow Diagram

1. Store: Store has responsibility of holding the state and applying changes to it when they are told to do so (when an action is dispatched). State is handled only in one object and in one place, so debugging or adding changes becomes way easier.
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).
2. Actions: Actions are objects that extend the NgRx Action class with a ‘type’ property. They have an optional ‘payload’ property (naming is up to you but the standard is to name it ‘payload’) for sending in data to the effect/reducer and are dispatched by the store to either run an effect or change state in a reducer.
3. Reducers: Reducers are pure functions which produce the same output for a given input. It takes the latest ‘Action’ dispatched, the current state, and determines whether to return a newly modified state or the original state.

Let’s Create An Example!

Here I will create a basic CRUD example, using Visual Studio Code, which is recommended editor to build client side applications with its powerful features.
1. Install Node Package Modules, by running below command in package console manager.
npm install --save
2. Install NgRx store.
npm install @ngrx/store --save
3. Add new folder employee in src/appfolder (like below) in your application.


4. Add new files (as shown below) insrc/app/employee’s folder.


5. Add new file app.reducer.ts in src/appfolder.


6. Add below lines of code intoapp/employee/employee.model.ts file. This is employee data structure which defines what type of data/properties we needed in this application.
export class Employee {
7. Add below lines of code intoapp/employee/employee.action.ts file.
Here each action has its own unique identifier. ‘type’ property for each action is mandatory to define, so that store will able to identify what type of action it needs to dispatch.
On the other hand, ‘payload’ property defines the data which needs to be pass at the time of action dispatching. Although, it is optional and it is not mandatory to have same name of this property. You can name it anything, but preferable is ‘payload’.
import { Action } from "@ngrx/store";
8. Add below lines of code intoapp/employee/employee.reducer.ts file.

 We define our state or state data in reducer. In employeeReducer function we set our state with initial state value and action as EmployeeActions type (which we have created in app/employee/employee.actions.ts file).
When any action get dispatched, the action will pass into the second argument of reducer by store itself and reducer then will call appropriate action method on the basis of its (currently dispatched action) type and perform following functionality.
It then returns update the state and send the modified state to the store by itself.
import {
9. Add below lines of code intoapp/app.reducer.ts file.
In here, we have defined our AppState. It tells us how our state will look like, when will fetch data from store.
import { ActionReducerMap } from "@ngrx/store";
10. Add StoreModule from @ngrx/store and add into imports array. Also import AppReducer and set it inside the forRootmethod of StoreModule.
StoreModule’s here will set our state, which we defined in app reducer in previous step. Hereby, we have set our NgRx basic structure for our application.
11. Now, go toapp/employee/employee.component.htmlfile and below html code.
In *ngFor, we are using async pipe on employees and then looping through the array to bind employees data.
While selecting state from store, the store will return an observable type state which further needed to fetch actual type of state in which our data is being stored.
So async pipe will allow to wait to fetch actual type of state from store to bind employees data. In detail about observables, click here.
<div class="container">
12. Add below lines of code intoapp/employee/employee.component.ts file.
Initialize store in constructor, and set it with state which is type AppState in our application. Now select ‘employeeState’ type from store which is actual state of application in which we are managing our employees data.
While selecting state from store, it will return an observable. So will take a property with same observable’s type and using it in html to bind employees data.
import { Component, OnInit, ViewChild, ElementRef } from "@angular/core";
13. Add below css code intoapp/employee/employee.component.cssfile.
.table-row-hover {cursor: pointer;}
14. Run below command in package console 


manager to start the application.
ng serve --open
15. It will start your application in browser and you can perform operations with such a clean and understandable structure of NgRx.

Effects in NgRx

In above example, if you have run this code, you will see that there is a button Fetch Employees, which is currently doing nothing while clicking on it.
Here, what we are going to learn one more important feature provided by NgRx is Effects.

Now what are Effects?

Effects are long-running services that listen to an observable of every action dispatched from the store.
A typical effect uses the Actions Observable as its source and uses the ofType operator to perform its side effect when the corresponding action is dispatched.
Let’s make it more clear by creating our own effect into same application.
1. First of all add new file employee.effects.tsin app/employee folder.
2. Replaceapp/employee/employee.actions.ts with below lines of code.
import { Action } from "@ngrx/store";
3. Replaceapp/employee/employee.reducer.ts with below lines of code.
Here, remove the static initialization of employees and set it as an empty array.
Will now fetch employees data using http service by implementing NgRx Effects.
import {
4. Add below lines of code inapp/employee/employee.effects.ts file.
Here, fetchEmployees is an effect. The effect listens to every action that gets dispatched and when it retrieves an action with the action type FETCH_EMPLOYEES, it will make an HTTP request. Depending on the response the effect will either dispatch a SetEmployees action.
import { Effect, Actions, ofType } from "@ngrx/effects";
5. Now add below lines of code inside the function fetchEmployees inapp/employee/employee.component.ts file.
this.store.dispatch(new FetchEmployees());
6. Run it using command ng serve — open in package console manager.
Now we are familiar with the NgRx life-cycle. We also know that what is the role of effects while creating such reactive applications using NgRx structure.
Let’s take a look for other interesting features provided by NgRx.

Store-DevTools in NgRx

The NgRx DevTools are browser extension that includes a UI for inspecting and interacting with a NgRx based application.

Features/ benefits of Store-DevTools

1. The key benefit of the DevTools is that it provides us visual feedback about what the application is doing at all times, making it much easier to understand what is going on.
2. Gives us a great understanding of how the application works, and what parts of application are triggering which Actions.
3. A State inspector, allows us to easily inspect the in-memory store state.

Installation of Store-DevTools

1. Run below command in package console manager to install store-devtools package in your application.
npm install @ngrx/store-devtools --save
2. Go to src/app/app.module.ts file.
Import StoreDevtoolsModule from@ngrx/store-devtools and set it into importsarray.
Now call instrument method, which takes an object, in which we are going to define our configurations for DevTools.
For an example, here I have set logOnlyproperty set to true for production build, which means it disables all extension features for production environment.
3. Now search for Redux DevTools extension and install it into your browser.
4. After successfully installing it, run your application and open developer tools in browser. You will now able to access all features of NgRx in there.

Router-Store in NgRx

NgRx Router Store provides binding which connects Angular router to Store. If you are working on some bigger reactive applications in which routing is also implemented. Here what NgRx Router Store comes with, without doing any extra efforts.
It simply uses the existing router navigation cycle and listens for changes router’s state, for each dispatched action, during this router navigation cycle.

Installation of Router-Store

1. Run below command in package console manager to install router-store in your application.
npm install @ngrx/router-store --save
2. Now go to src/app/app.module.ts file and import StoreRouterConnectingModule from @ngrx/router-store.


 Then, set into imports array and call forRootmethod. That’s it, its hereby will automatically connects your existing Angular router to Store.

Error Handling

A very basic and most important part of our application is error handling. Error handling is something when some lines of code get would get break or some http service gets failed.
Here we will learn that how do we handle such exceptions using NgRx observables.
Let’s take an example with our application, where we will handle exception while our http service gets failed.
1. Add new action HANDLE_ERROR inapp/employees/employee.action.ts file. And create new action class to define this action.
2. Now add a new case inapp/employees/employees.reducer.ts file.
You can define your own error display logic. Here I am simply showing error message in alert box and returning the original state.
3. Add catchError (import from rxjs/operators) just like below, in app/employees/employee.effects.ts file.
catchError will return an observable and dispatch HandleError action to log or display the actual error.
This is it!
So now we have learnt that how do we build reactive applications in Angular by implementing NgRx structure. Although, this is an short example just to understood that how NgRx life-cycle works, we can use this structure in bigger applications where we need state management on client side and perform other operations with our data and store back into a state.

Wrap Up

  1. We have learnt about the state management in NgRx.
  2. Understood the life-cycle of NgRx and what is the role of store, reducers and actions in complete life-cycle.
  3. We discussed about NgRx Effects, Store-DevTools and Router-Store, which are great tools/ features provided by NgRx.
  4. Last but not least, we have learnt about the error handling in NgRx Effects which will be really very helpful to manage our application and display meaningful error messages on UI.

Comments

Popular posts from this blog

Understand Angular’s forRoot and forChild

  forRoot   /   forChild   is a pattern for singleton services that most of us know from routing. Routing is actually the main use case for it and as it is not commonly used outside of it, I wouldn’t be surprised if most Angular developers haven’t given it a second thought. However, as the official Angular documentation puts it: “Understanding how  forRoot()  works to make sure a service is a singleton will inform your development at a deeper level.” So let’s go. Providers & Injectors Angular comes with a dependency injection (DI) mechanism. When a component depends on a service, you don’t manually create an instance of the service. You  inject  the service and the dependency injection system takes care of providing an instance. import { Component, OnInit } from '@angular/core'; import { TestService } from 'src/app/services/test.service'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.compon...

How to use Ngx-Charts in Angular ?

Charts helps us to visualize large amount of data in an easy to understand and interactive way. This helps businesses to grow more by taking important decisions from the data. For example, e-commerce can have charts or reports for product sales, with various categories like product type, year, etc. In angular, we have various charting libraries to create charts.  Ngx-charts  is one of them. Check out the list of  best angular chart libraries .  In this article, we will see data visualization with ngx-charts and how to use ngx-charts in angular application ? We will see, How to install ngx-charts in angular ? Create a vertical bar chart Create a pie chart, advanced pie chart and pie chart grid Introduction ngx-charts  is an open-source and declarative charting framework for angular2+. It is maintained by  Swimlane . It is using Angular to render and animate the SVG elements with all of its binding and speed goodness and uses d3 for the excellent math functio...

How to solve Puppeteer TimeoutError: Navigation timeout of 30000 ms exceeded

During the automation of multiple tasks on my job and personal projects, i decided to move on  Puppeteer  instead of the old school PhantomJS. One of the most usual problems with pages that contain a lot of content, because of the ads, images etc. is the load time, an exception is thrown (specifically the TimeoutError) after a page takes more than 30000ms (30 seconds) to load totally. To solve this problem, you will have 2 options, either to increase this timeout in the configuration or remove it at all. Personally, i prefer to remove the limit as i know that the pages that i work with will end up loading someday. In this article, i'll explain you briefly 2 ways to bypass this limitation. A. Globally on the tab The option that i prefer, as i browse multiple pages in the same tab, is to remove the timeout limit on the tab that i use to browse. For example, to remove the limit you should add: await page . setDefaultNavigationTimeout ( 0 ) ;  COPY SNIPPET The setDefaultNav...