State Management With NgRx Store

In this article, we’ll learn how to implement state management with NgRx in an Angular application. For that first, we need to discuss what is NgRx and State Management.
NgRx : It’s redux pattern with RxJs. Redux works on the concept of reducers or more specifically, the reduce method for arrays in Javascript.
NgRx App State Management

  • Store: It store data is what holds the app’s state
  • Action: It’s a unique event dispatched from components and services that describe how the state should be changed.
  • Reducer: All the state changeing happen inside the reducer; it responds to the action and, based on that action, it will create a new immutable state and return it to the store.
  • Selector: Selector is a function used for obtaining a part of the state from the store.
  • Effect: It’s mechanism that listens for dispatched actions in an observable stream, processes the server response, and returns new actions either immediately or asynchronously to the reducer to change the state.

The life cycle of NgRx displays in the below Diagram.
life cycle
Let’s create a simple add for adding customers and remove customers using NgRx Store.


Let’s create a new project to demo for NgRx state management. For that, first, we need an angular project to create a project run below command.


ng new state-management-demo

“state-management-demo” you need to write your application’s name. Then it will take some time to create the project. After successfully installing that, you need to go to their directory. For example “cd state-management-demo”. To Run angular applications, it required to run “ng serve”.
After that, we need to install the “@ngrx/store” npm package in our application. run below command to install.


npm i @ngrx/store --save

After install let’s create class for customer model. for that run below code.


ng g class models/customer 

After creating class add belo code init.


export class Customer {
  name: String = '';
}

Let’s implemnt Actions we need for the customer. Mainly there is 2 action we create addCustomer and removeCustomer. Let’s create a “customer.actions.ts” file and add the below code their.


import {Action} from '@ngrx/store';
export enum CustomerActionTypes {
  Add = '[Customer Component] Add',
  Remove = '[Customer Component] Remove'
}
export class ActionEx implements Action {
  readonly type;
  payload: any;
}
export class CustomerAdd implements ActionEx {
  readonly type = CustomerActionTypes.Add;
  constructor(public payload: any) {
  }
}
export class CustomerRemove implements ActionEx {
  readonly type = CustomerActionTypes.Remove;
  constructor(public payload: any) {
  }
}

After creating Action now we need to create nor Reducer. Let’s create a “customer.reducer.ts” file and add the below code their.


import {ActionEx, CustomerActionTypes} from './customer.actions';
export const initialState = [];
export function CustomerReducer(state = initialState, action: ActionEx) {
  switch (action.type) {
    case CustomerActionTypes.Add:
      return [...state, action.payload];
    case CustomerActionTypes.Remove:
      return [
        ...state.slice(0, action.payload),
        ...state.slice(action.payload + 1)
      ];
    default:
      return state;
  }
}

Now its time to add reducer and ngrx in our module file.


import { StoreModule } from '@ngrx/store';
import { CustomerReducer } from './customer.reducer';
@NgModule({
  declarations: [
    ...........
  ],
  imports: [
   ........
    StoreModule.forRoot({ customers: CustomerReducer })
  ],
  providers: [],
  bootstrap: [AppComponent]
})

After adding let’s create 2 component for customer View & Add. for that run below command and Add below code in the component.


ng g c  customers-view
ng g c  customers-add



customers-view Code


import {Component} from '@angular/core';
import {Customer} from '../models/customer';
import {Observable} from 'rxjs';
import {select, Store} from '@ngrx/store';
import {CustomerRemove} from '../customer.actions';
@Component({
  selector: 'app-customers-view',
  templateUrl: './customers-view.component.html',
  styleUrls: ['./customers-view.component.css']
})
export class CustomersViewComponent {
  customers: Observable<Customer[]>;
  constructor(private store: Store<{ customers: Customer[] }>) {
    this.customers = store.pipe(select('customers'));
  }

  removeCustomer(customerIndex) {
    this.store.dispatch(new CustomerRemove(customerIndex));
  }
}


<h4>List of Customers</h4>
<ul class="customers">
  <li *ngFor="let customer of customers | async; let i=index">
    <span >{{i+1}}.</span> {{customer.name}}
    <button style="float: right" (click)="removeCustomer(i)">Remove</button>
  </li>
</ul>

customers-add Code


import {Component} from '@angular/core';
import {select, Store} from '@ngrx/store';
import {Customer} from '../models/customer';
import {Observable} from 'rxjs';
import {CustomerAdd} from '../customer.actions';
@Component({
  selector: 'app-customer-add',
  templateUrl: './customer-add.component.html',
  styleUrls: ['./customer-add.component.css']
})
export class CustomerAddComponent {
  customers: Observable<Customer[]>;
  constructor(private store: Store<{ customers: Customer[] }>) {
    this.customers = store.pipe(select('customers'));
  }
  AddCustomer(customerName: string) {
    const customer = new Customer();
    customer.name = customerName;
    this.store.dispatch(new CustomerAdd(customer));
  }
}


<h3>Add New Customer</h3>
<input #box ><button (click)="AddCustomer(box.value)">Add</button>


Let’s add both component in our app.component.html file to display the output. Let’s add below code.


<div style="text-align:center">
  <h1> Welcome to {{ title }}</h1>
</div>
<app-customers-view></app-customers-view>
<app-customer-add></app-customer-add>

Output

Spread the love
  •  
  •  
  •  
  •  
  • 3
  • 5
  •  
  •