Skip to content

Latest commit

 

History

History
127 lines (91 loc) · 4.3 KB

State Management.md

File metadata and controls

127 lines (91 loc) · 4.3 KB

State Management in Angular with NgRx

Managing state in large-scale Angular applications can be challenging. NgRx provides a reactive state management solution inspired by Redux that works with Angular's unidirectional data flow. This guide covers the fundamentals of NgRx and how to integrate it into your Angular applications.

Table of Contents


Understanding NgRx

NgRx is a framework for building reactive applications in Angular. It provides libraries for managing global and local state, isolation of side effects, entity collection management, and integration with the Angular Router.

Core Principles of NgRx

  • State: Described by a single immutable data structure managed by NgRx store, which is a controlled state container designed to help write performant, consistent applications.
  • Actions: Express unique events that are dispatched from components and services.
  • Reducers: Pure functions that take the previous state and the latest action to compute a new state.
  • Effects: Model side effects such as fetching data, long-running tasks that produce other actions.

Using NgRx in Angular

Integrating NgRx into an Angular application involves setting up reducers, actions, and effects to facilitate the features of Redux-like state management.

Setting Up NgRx

  1. Install NgRx

    Start by installing NgRx in your project with npm or yarn:

    npm install @ngrx/store @ngrx/effects @ngrx/store-devtools @ngrx/router-store --save
  2. Define Actions

    Actions define unique events that change the state. Define actions using the createAction function:

    import { createAction } from '@ngrx/store';
    
    export const loadItems = createAction('[Item List] Load Items');
    export const addItemSuccess = createAction('[Item List] Add Item Success', props<{ item: any }>());
  3. Create Reducers

    Reducers handle state changes. Create a reducer using the createReducer function:

    import { createReducer, on } from '@ngrx/store';
    import { loadItems, addItemSuccess } from './item.actions';
    
    export const initialState = { items: [] };
    
    const _itemReducer = createReducer(
      initialState,
      on(loadItems, state => ({ ...state })),
      on(addItemSuccess, (state, { item }) => ({ ...state, items: [...state.items, item] }))
    );
    
    export function itemReducer(state, action) {
      return _itemReducer(state, action);
    }
  4. Configure Effects

    Effects handle asynchronous operations and side effects. Define effects using the createEffect function:

    import { Injectable } from '@angular/core';
    import { Actions, ofType, createEffect } from '@ngrx/effects';
    import { of } from 'rxjs';
    import { map, mergeMap, catchError } from 'rxjs/operators';
    import { ItemService } from './item.service';
    import { loadItems, addItemSuccess } from './item.actions';
    
    @Injectable()
    export class ItemEffects {
    
      loadItems$ = createEffect(() => this.actions$.pipe(
        ofType(loadItems),
        mergeMap(() => this.itemService.getAll()
          .pipe(
            map(items => ({ type: '[Items API] Items Loaded Success', payload: items })),
            catchError(() => of({ type: '[Items API] Items Loaded Error' }))
          )
        )
      ));
    
      constructor(
        private actions$: Actions,
        private itemService: ItemService
      ) {}
    }
  5. Register State and Effects in the Module

    Finally, import your state and effects into the Angular module:

    import { StoreModule } from '@ngrx/store';
    import { EffectsModule } from '@ngrx/effects';
    import { itemReducer } from './reducers/item.reducer';
    import { ItemEffects } from './effects/item.effects';
    
    @NgModule({
      declarations: [AppComponent],
      imports: [
        BrowserModule,
        StoreModule.forRoot({ items: itemReducer }),
        EffectsModule.forRoot([ItemEffects])
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule {}

Utilizing NgRx in your Angular applications provides a robust, scalable approach to managing state with reactive programming principles, making it ideal for complex applications with high performance demands.