NashTech Insights

Implementing State Management with NgRx in Angular

Alka Vats
Alka Vats
Table of Contents

Introduction

State management is a crucial aspect of building complex Angular applications. NgRx is a powerful library that implements the Redux pattern for managing application state. In this blog post, we will explore the key concepts of NgRx and demonstrate how to implement state management using NgRx in Angular with practical examples.

If you want to learn about a new feature of angular, you can refer here.

Understanding the Redux Pattern:

Redux follows a unidirectional data flow, where the state of an application is stored in a single immutable state tree. Actions are dispatched to describe state changes, and pure functions called reducers handle these actions to produce a new state. NgRx builds upon this pattern to provide a robust state management solution for Angular applications.

Setting Up NgRx:

To use it in your Angular project, you need to install the required packages and configure the store. Follow these steps:

Step 1: Install NgRx packages:
npm install @ngrx/store @ngrx/effects @ngrx/entity @ngrx/store-devtools
Step 2: Configure the store:

In your app.module.ts file, import the necessary NgRx modules and configure the store using the StoreModule.forRoot() method. Additionally, set up the NgRx DevTools for easier debugging.

import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';

@NgModule({
  imports: [
    StoreModule.forRoot(appReducers),
    EffectsModule.forRoot([AppEffects]),
    StoreDevtoolsModule.instrument()
  ],
  ...
})
export class AppModule { }

Defining Actions, Reducers, and Selectors:

Actions describe events that occur in the application. Reducers are pure functions that take the current state and an action and return a new state. Selectors allow you to retrieve specific portions of the state.

Step 1: Define actions:

Create action files to define the actions that can occur in your application. For example:

import { createAction, props } from '@ngrx/store';

export const increment = createAction('[Counter] Increment');
export const decrement = createAction('[Counter] Decrement');
export const reset = createAction('[Counter] Reset');
Step 2: Create reducers:

Create reducer files to handle the actions and update the state accordingly. For example:

import { createReducer, on } from '@ngrx/store';
import { increment, decrement, reset } from './counter.actions';

export interface CounterState {
  count: number;
}

const initialState: CounterState = {
  count: 0
};

export const counterReducer = createReducer(
  initialState,
  on(increment, state => ({ ...state, count: state.count + 1 })),
  on(decrement, state => ({ ...state, count: state.count - 1 })),
  on(reset, state => ({ ...state, count: 0 }))
);
Step 3: Define selectors:

Create selector files to retrieve specific portions of the state. For example:

import { createSelector, createFeatureSelector } from '@ngrx/store';
import { CounterState } from './counter.reducer';

export const selectCounterState = createFeatureSelector<CounterState>('counter');

export const selectCount = createSelector(
  selectCounterState,
  (state: CounterState) => state.count
);

Dispatching Actions and Subscribing to State Changes:

To dispatch actions and subscribe to state changes, you’ll need to make use of NgRx in your components and services.

Step 1: Dispatch actions:

In your component or service, import the actions and dispatch them using the NgRx Store or Actions service. For example:

import { increment, decrement, reset } from './counter.actions';
import { Store } from '@ngrx/store';

export class MyComponent {
  constructor(private store: Store) {}

  incrementCounter() {
    this.store.dispatch(increment());
  }

  // Other methods for decrementing and resetting the counter
}
Step 2: Subscribe to state changes:

To receive updates when the state changes, you can subscribe to the store and select specific portions of the state using selectors. For example:

import { selectCount } from './counter.selectors';
import { Observable } from 'rxjs';
import { Store } from '@ngrx/store';

export class MyComponent {
  count$: Observable<number>;

  constructor(private store: Store) {
    this.count$ = this.store.select(selectCount);
  }
}

Effects and Asynchronous Operations:

NgRx Effects allow you to handle asynchronous operations, such as making API calls or performing side effects. Effects listen to actions and can dispatch new actions based on the result of the operations.

Step 1: Create effect files:

Create effect files to define the side effects and their corresponding actions. For example:

import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { mergeMap, map } from 'rxjs/operators';
import { DataService } from './data.service';
import { loadItems, loadItemsSuccess } from './item.actions';

@Injectable()
export class ItemEffects {
  loadItems$ = createEffect(() =>
    this.actions$.pipe(
      ofType(loadItems),
      mergeMap(() =>
        this.dataService.getItems().pipe(
          map(items => loadItemsSuccess({ items }))
        )
      )
    )
  );

  constructor(private actions$: Actions, private dataService: DataService) {}
}
Step 2: Register effects in the module:

In the EffectsModule.forRoot() method, register the effects you’ve defined. For example:

import { EffectsModule } from '@ngrx/effects';
import { ItemEffects } from './item.effects';

@NgModule({
  imports: [
    EffectsModule.forRoot([ItemEffects])
  ]
})
export class AppModule { }

Conclusion:

NgRx provides a powerful state management solution for Angular applications, enabling you to efficiently manage application states and handle complex scenarios. By following the steps outlined in this blog post, you can implement state management with NgRx in your Angular projects, promoting scalability, maintainability, and testability. Embrace the power of NgRx and take your Angular applications to the next level of state management excellence. Happy coding!

Finally, for more such posts, please follow our LinkedIn page- FrontEnd Competency.

Alka Vats

Alka Vats

Alka Vats is a Software Consultant at Nashtech. She is passionate about web development. She is recognized as a good team player, a dedicated and responsible professional, and a technology enthusiast. She is a quick learner & curious to learn new technologies. Her hobbies include reading books, watching movies, and traveling.

Leave a Comment

Your email address will not be published. Required fields are marked *

Suggested Article

%d bloggers like this: