Skip to content

C'est quoi une action sur NgRx ?

L'action est un concept central dans NgRx et d'autres bibliothèques de gestion d'état réactif. Elle représente une intention de modification de l'état de l'application. Une action est généralement implémentée en tant qu'objet simple contenant des informations sur l'intention de modification de l'état.

Voici un exemple simple d'une action pour un compteur :

ts
// counter.actions.ts
import { Action } from '@ngrx/store';

export const INCREMENT = '[Counter] Increment';
export const DECREMENT = '[Counter] Decrement';

export class Increment implements Action {
  readonly type = INCREMENT;
}

export class Decrement implements Action {
  readonly type = DECREMENT;
}

export type Actions = Increment | Decrement;
// counter.actions.ts
import { Action } from '@ngrx/store';

export const INCREMENT = '[Counter] Increment';
export const DECREMENT = '[Counter] Decrement';

export class Increment implements Action {
  readonly type = INCREMENT;
}

export class Decrement implements Action {
  readonly type = DECREMENT;
}

export type Actions = Increment | Decrement;

Dans cet exemple, l'action Increment est définie en tant que classe qui implémente l'interface Action de NgRx. Cette classe contient un champ type qui indique le type de l'action, qui sera utilisé par le reducer pour mettre à jour l'état en conséquence. De manière similaire, l'action Decrement est définie en tant que classe qui implémente l'interface Action.

Comment utiliser l'action dans le composant ?

Les actions sont généralement dispatchées à partir des composants de l'application en utilisant la méthode store.dispatch() du store NgRx :

ts
// app.component.ts
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';

import * as fromRoot from './reducers';
import * as counterActions from './actions/counter';

@Component({
  selector: 'app-root',
  template: `
    <h1>Compteur : {{ counter$ | async }}</h1>
    <button (click)="increment()">Incrémenter</button>
    <button (click)="decrement()">Décrémenter</button>
  `
})
export class AppComponent {
  counter$: Observable<number>;

  constructor(private store: Store<fromRoot.State>) {
    this.counter$ = store.select(fromRoot.getCounter);
  }

  increment() {
    this.store.dispatch(new counterActions.Increment());
  }

  decrement() {
    this.store.dispatch(new counterActions.Decrement());
  }
}
// app.component.ts
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';

import * as fromRoot from './reducers';
import * as counterActions from './actions/counter';

@Component({
  selector: 'app-root',
  template: `
    <h1>Compteur : {{ counter$ | async }}</h1>
    <button (click)="increment()">Incrémenter</button>
    <button (click)="decrement()">Décrémenter</button>
  `
})
export class AppComponent {
  counter$: Observable<number>;

  constructor(private store: Store<fromRoot.State>) {
    this.counter$ = store.select(fromRoot.getCounter);
  }

  increment() {
    this.store.dispatch(new counterActions.Increment());
  }

  decrement() {
    this.store.dispatch(new counterActions.Decrement());
  }
}

Dans cet exemple, le composant AppComponent affiche le compteur et permet à l'utilisateur d'incrémenter ou de décrémenter le compteur en cliquant sur les boutons correspondants. Lorsque l'utilisateur clique sur l'un des boutons, le composant dispatch une action au store NgRx en appelant la méthode store.dispatch(). Le store utilisera alors le reducer associé à l'état du compteur pour mettre à jour l'état en conséquence.

Le composant s'abonne également à l'Observable du compteur depuis le store NgRx en appelant la méthode store.select(). Cet Observable est utilisé dans le template du composant pour afficher la valeur actuelle du compteur. Lorsque l'état du compteur est mis à jour par le store, l'Observable notifie le composant, qui met à jour son état en conséquence.