In Angular, the State Management pattern is critical for managing complicated application states. NgRx (Redux-inspired), Akita, and Ngxs are some of the most popular state management libraries. Here's an example of how to use NgRx in Angular for state management:
NgRx should be installed.
To install NgRx, open your Angular project in a terminal and perform the following command:
Define your Actions
To define the activities that can be dispatched, create action files. Create a file called user.actions.ts with the following code:
import { createAction, props } from '@ngrx/store';
import { User } from './user.model';
export const loadUsers = createAction('[User] Load Users');
export const loadUsersSuccess = createAction('[User] Load Users Success', props<{ users: User[] }>());
export const loadUsersFailure = createAction('[User] Load Users Failure', props<{ error: string }>());
Make Reducers
Create reducer files to specify how the state changes as a result of actions. Create a file called user.reducer.ts with the following code:
import { createReducer, on } from '@ngrx/store';
import { User } from './user.model';
import * as UserActions from './user.actions';
export interface UserState {
users: User[];
loading: boolean;
error: string | null;
}
const initialState: UserState = {
users: [],
loading: false,
error: null,
};
export const userReducer = createReducer(
initialState,
on(UserActions.loadUsers, (state) => ({ ...state, loading: true, error: null })),
on(UserActions.loadUsersSuccess, (state, { users }) => ({ ...state, users, loading: false })),
on(UserActions.loadUsersFailure, (state, { error }) => ({ ...state, loading: false, error }))
);
Define Selectors
Create selector files to extract specific data from the state. For example, create a file named user.selectors.ts with the following code:
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { UserState } from './user.reducer';
export const selectUserState = createFeatureSelector<UserState>('user');
export const selectUsers = createSelector(selectUserState, (state) => state.users);
export const selectLoading = createSelector(selectUserState, (state) => state.loading);
export const selectError = createSelector(selectUserState, (state) => state.error);
Use NgRx in a Component
Create a component that utilizes NgRx for state management. For example, create a file named user.component.ts with the following code:
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { User } from './user.model';
import * as UserActions from './user.actions';
import { selectUsers, selectLoading, selectError } from './user.selectors';
@Component({
selector: 'app-user',
template: `
<h2>User Component</h2>
<div *ngIf="loading">Loading...</div>
<div *ngIf="error">{{ error }}</div>
<ul>
<li *ngFor="let user of users">{{ user.name }}</li>
</ul>
`,
})
export class UserComponent implements OnInit {
users$: Observable<User[]>;
loading$: Observable<boolean>;
error$: Observable<string>;
constructor(private store: Store) {}
ngOnInit(): void {
this.users$ = this.store.select(selectUsers);
this.loading$ = this.store.select(selectLoading);
this.error$ = this.store.select(selectError);
this.store.dispatch(UserActions.loadUsers());
}
}
Build and run the application: Use the following command to build and serve the Angular application:
ng serve
Your application will be accessible at http://localhost:4200.
In this example, NgRx is used for state management. Actions are dispatched to trigger state changes, reducers define how the state changes, and selectors are used to extract specific data from the state. The UserComponent subscribes to the state using NgRx's select method and displays the data in the template.
By following the State Management pattern with NgRx or other state management libraries, you can centralize and manage complex application states efficiently, leading to better code organization, maintainability, and scalability.