NgRx Store (Classique)
NgRx implémente le patron Redux pour Angular. L’état est immuable ; les modifications se font via des actions dispatchées vers des reducers.
Installation
Section intitulée « Installation »npm install @ngrx/store @ngrx/effects @ngrx/store-devtoolsConcepts fondamentaux
Section intitulée « Concepts fondamentaux »| Concept | Rôle |
|---|---|
| Store | Source unique de vérité ; contient tout l’état de l’application |
| Action | Décrit ce qui s’est passé ([Source] Événement) |
| Reducer | Fonction pure : (état, action) → nouvel état |
| Selector | Projection mémoïsée de l’état |
| Effect | Gère les effets secondaires (HTTP, routage) déclenchés par des actions |
import { createAction, props } from '@ngrx/store';
export const loadAlbums = createAction('[Album] Charger');export const loadAlbumsSuccess = createAction( '[Album] Chargement réussi', props<{ albums: Album[] }>());export const loadAlbumsFailure = createAction( '[Album] Échec du chargement', props<{ error: string }>());import { createReducer, on } from '@ngrx/store';
export interface AlbumState { albums: Album[]; loading: boolean; error: string | null;}
const initialState: AlbumState = { albums: [], loading: false, error: null };
export const albumReducer = createReducer( initialState, on(loadAlbums, state => ({ ...state, loading: true })), on(loadAlbumsSuccess, (state, { albums }) => ({ ...state, albums, loading: false })), on(loadAlbumsFailure, (state, { error }) => ({ ...state, error, loading: false })));Sélecteurs
Section intitulée « Sélecteurs »import { createFeatureSelector, createSelector } from '@ngrx/store';
const selectAlbumState = createFeatureSelector<AlbumState>('albums');
export const selectAllAlbums = createSelector(selectAlbumState, s => s.albums);export const selectLoading = createSelector(selectAlbumState, s => s.loading);import { Injectable } from '@angular/core';import { Actions, createEffect, ofType } from '@ngrx/effects';import { switchMap, map, catchError, of } from 'rxjs';
@Injectable()export class AlbumEffects { load$ = createEffect(() => this.actions$.pipe( ofType(loadAlbums), switchMap(() => this.albumService.getAlbums().pipe( map(albums => loadAlbumsSuccess({ albums })), catchError(err => of(loadAlbumsFailure({ error: err.message }))) ) ) ) );
constructor(private actions$: Actions, private albumService: AlbumService) {}}Câblage (app.config.ts)
Section intitulée « Câblage (app.config.ts) »import { provideStore } from '@ngrx/store';import { provideEffects } from '@ngrx/effects';import { provideStoreDevtools } from '@ngrx/store-devtools';
export const appConfig: ApplicationConfig = { providers: [ provideStore({ albums: albumReducer }), provideEffects([AlbumEffects]), provideStoreDevtools({ maxAge: 25 }), ],};Utilisation dans un composant
Section intitulée « Utilisation dans un composant »export class AlbumListComponent { private store = inject(Store);
albums$ = this.store.select(selectAllAlbums); loading$ = this.store.select(selectLoading);
ngOnInit() { this.store.dispatch(loadAlbums()); }}@if (loading$ | async) { <p>Chargement…</p> }@for (album of albums$ | async; track album.id) { <app-album-card [album]="album" />}NgRx Classique vs Signal Store
Section intitulée « NgRx Classique vs Signal Store »| Fonctionnalité | NgRx Classique | Signal Store |
|---|---|---|
| Patron | Redux | Natif Signals |
| Boilerplate | Élevé | Faible |
| DevTools | Redux DevTools | NgRx DevTools (Angular 17+) |
| Réactivité | Observables | Signals |
| Idéal pour | Grandes équipes, état complexe | Applications Angular modernes |

