Tag: state management

  • State Management in Angular using Ngrx

    State Management in Angular using Ngrx

    In Angular, we use state management libraries like ngrx to handle complex data flows in large applications. ngrx is a reactive state management library based on the Redux pattern, which provides a way to manage state changes in Angular applications. It uses Observables, Actions, Reducers, and Effects to manage state changes.

    In this blog, we will discuss the steps to use ngrx in an Angular application and understand its flow.
    Step 1: Install ngrx

    First, we need to install ngrx using the npm package manager.

    npm install @ngrx/store --save

    Step 2: Define the state

    The state is the data that we want to manage in the application. We define the state using an interface in a separate file. For example, we can define a state interface for a counter application as follows:

    typescript
    export interface CounterState {
    count: number;
    }

    Step 3: Define the actions

    Actions describe the changes that occur in the application. We define actions using an enum in a separate file. For example, we can define actions for a counter application as follows:

    typescript
    import { createAction } from ‘@ngrx/store’;

    export enum CounterActionTypes {
    Increment = ‘[Counter] Increment’,
    Decrement = ‘[Counter] Decrement’,
    }

    export const increment = createAction(
    CounterActionTypes.Increment
    );

    export const decrement = createAction(
    CounterActionTypes.Decrement
    );

    Step 4: Define the reducers

    Reducers specify how the application state changes in response to actions. We define reducers in a separate file. For example, we can define reducers for a counter application as follows:

    typescript
    import { createReducer, on } from ‘@ngrx/store’;
    import { CounterActionTypes } from ‘./counter.actions’;
    import { CounterState } from ‘./counter.state’;

    export const initialState: CounterState = {
    count: 0,
    };

    export const counterReducer = createReducer(
    initialState,
    on(CounterActionTypes.Increment, (state) => ({
    count: state.count + 1,
    })),
    on(CounterActionTypes.Decrement, (state) => ({
    count: state.count – 1,
    }))
    );

    Step 5: Define the effects

    Effects are used for handling asynchronous operations, such as HTTP requests. We define effects in a separate file. For example, we can define effects for a counter application as follows:

    typescript
    import { Injectable } from ‘@angular/core’;
    import { Actions, createEffect, ofType } from ‘@ngrx/effects’;
    import { Observable, of } from ‘rxjs’;
    import { map, catchError, mergeMap } from ‘rxjs/operators’;
    import { CounterActionTypes, increment } from ‘./counter.actions’;

    @Injectable()
    export class CounterEffects {
    increment$ = createEffect(() =>
    this.actions$.pipe(
    ofType(CounterActionTypes.Increment),
    mergeMap(() =>
    this.myService.increment().pipe(
    map(() => increment()),
    catchError(() => of({ type: ‘API Error’ }))
    )
    )
    )
    );

    constructor(private actions$: Actions, private myService: MyService) {}
    }

    Step 6: Register the state, actions, reducers, and effects

    We register the state, actions, reducers, and effects in the app.module.ts file as follows:

    typescript
    import { NgModule } from ‘@angular/core’;
    import { BrowserModule } from ‘@angular/platform-browser’;
    import { AppComponent } from ‘./app.component’;
    import { StoreModule } from ‘@ngrx/store’;
    import { EffectsModule } from ‘@ngrx/effects’;
    import { counterReducer } from ‘./counter.reducer’;
    import { CounterEffects } from ‘./counter.effects’;

    @NgModule({
      declarations: [AppComponent],
      imports: