DEV Community

Indraja
Indraja

Posted on

2

State Management in Angular with NgRx: A Complete Guide

Introduction

Managing state in large Angular applications can become challenging. This is where NgRx comes in! NgRx is a state management library based on the Redux pattern, designed specifically for Angular applications.

In this guide, we'll explore:

  • Why you need NgRx in Angular
  • The core concepts of NgRx
  • How to implement NgRx step-by-step
  • Best practices for efficient state management

Let's get started!

🔥 Why Use NgRx?

Before jumping into implementation, let's understand why NgRx is beneficial:

Centralized State Management - Stores data in a single place, making it predictable.

Time-Travel Debugging - Inspect and revert state changes.

Optimized Performance - Uses immutable state updates for better performance.

Scalability - Suitable for large, complex applications.

🛠️ Installing NgRx in Angular

To get started with NgRx, install the necessary packages:

ng add @ngrx/store @ngrx/effects @ngrx/store-devtools
Enter fullscreen mode Exit fullscreen mode

This command adds NgRx Store, Effects, and DevTools for debugging.


🏗️ Understanding NgRx Core Concepts

NgRx consists of several key building blocks:

1️⃣ Actions

Actions define events that describe what happens in the app.

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

export const loadUsers = createAction('[User] Load Users');
export const loadUsersSuccess = createAction('[User] Load Users Success', props<{ users: any[] }>());
export const loadUsersFailure = createAction('[User] Load Users Failure', props<{ error: string }>());
Enter fullscreen mode Exit fullscreen mode

2️⃣ Reducers

Reducers specify how state changes in response to actions.

import { createReducer, on } from '@ngrx/store';
import { loadUsersSuccess } from './user.actions';

export interface UserState {
  users: any[];
}

const initialState: UserState = {
  users: []
};

export const userReducer = createReducer(
  initialState,
  on(loadUsersSuccess, (state, { users }) => ({ ...state, users }))
);
Enter fullscreen mode Exit fullscreen mode

3️⃣ Selectors

Selectors help retrieve specific parts of the state.

import { createSelector, createFeatureSelector } from '@ngrx/store';
import { UserState } from './user.reducer';

export const selectUserState = createFeatureSelector<UserState>('user');
export const selectUsers = createSelector(selectUserState, (state) => state.users);
Enter fullscreen mode Exit fullscreen mode

4️⃣ Effects

Effects handle side effects like API calls.

import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { UserService } from '../services/user.service';
import { loadUsers, loadUsersSuccess } from './user.actions';
import { mergeMap, map } from 'rxjs/operators';

@Injectable()
export class UserEffects {
  loadUsers$ = createEffect(() =>
    this.actions$.pipe(
      ofType(loadUsers),
      mergeMap(() => this.userService.getUsers()
        .pipe(map(users => loadUsersSuccess({ users })))
      )
    )
  );

  constructor(private actions$: Actions, private userService: UserService) {}
}
Enter fullscreen mode Exit fullscreen mode

🛠️ Integrating NgRx in an Angular Module

Add the store and effects module to your app module:

import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { userReducer } from './store/user.reducer';
import { UserEffects } from './store/user.effects';

@NgModule({
  imports: [
    StoreModule.forRoot({ user: userReducer }),
    EffectsModule.forRoot([UserEffects])
  ]
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Using NgRx in Angular Components

🔍 Selecting Data from Store

Use select to get data from the store:

import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { selectUsers } from './store/user.selectors';

@Component({
  selector: 'app-user-list',
  template: `<ul><li *ngFor="let user of users$ | async">{{ user.name }}</li></ul>`
})
export class UserListComponent {
  users$ = this.store.select(selectUsers);

  constructor(private store: Store) {}
}
Enter fullscreen mode Exit fullscreen mode

🏗️ Dispatching Actions

Dispatch actions to update state:

this.store.dispatch(loadUsers());
Enter fullscreen mode Exit fullscreen mode

Best Practices for NgRx

✅ Use Selectors for optimized state retrieval.

✅ Keep Effects independent from components.

✅ Use Immutable State - always return new objects in reducers.

✅ Organize your store into feature modules for scalability.


📌 Conclusion

NgRx provides a powerful way to manage application state in Angular. By using Actions, Reducers, Selectors, and Effects, you can create scalable and maintainable applications.

Have any questions? Drop them in the comments! 👇


💡 Further Reading:

📌 NgRx Official Documentation

📌 Redux Pattern Explained

Happy coding! 🎉

Heroku

Deploy with ease. Manage efficiently. Scale faster.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

👋 Kindness is contagious

If you found this post helpful, please leave a ❤️ or a friendly comment below!

Okay