Un reducer est une fonction pure qui détermine comment l’état de l’application évolue en réponse à une action. C’est le cerveau de la logique de mise à jour : il prend l’ancien état et l’action reçue, calcule le prochain état et le retourne.
Signature de la fonction :
javascript
(étatPrécédent, action) => nouvelÉtat
Principe clé :
Contrairement à ce que son nom pourrait suggérer, le reducer ne « réduit » pas l’état au sens propre. Il « accumule » les changements : il reçoit un état initial et une liste d’actions, et les combine progressivement pour produire l’état final. C’est l’analogue de la méthode Array.reduce() qui accumule des valeurs au fil du temps .
Les règles d’or d’un Reducer (les 3 piliers de la pureté)
Un reducer doit respecter des règles strictes, héritées des principes de Redux . Elles garantissent la prévisibilité et la maintenabilité de l’application :
| Règle | Explication | Exemple |
|---|---|---|
| 1. Pureté | Le reducer ne doit jamais modifier l’état existant. Il doit produire un nouvel objet d’état pour chaque mise à jour . | Mauvaise pratique : state.valeur = 5 (mutation). Bonne pratique : { ...state, valeur: 5 } (copie). |
| 2. Pas d’effets de bord | Il ne doit pas effectuer d’appels API, de manipulations du DOM, ou d’opérations asynchrones. Il doit être synchrone et prédictible . | Un reducer ne fait jamais de fetch(). |
| 3. Déterminisme | Étant donné les mêmes arguments (état et action), le reducer doit toujours retourner exactement le même résultat. Ni le temps, ni l’ordre d’appel ne doivent influencer le résultat . | (state, action) => newState est une fonction mathématique pure. |
Comment ça fonctionne concrètement ?
- Définition du state initial : Le reducer définit une valeur par défaut pour l’état (généralement via un paramètre
state = initialState). - Écoute des actions : Le reducer examine la propriété
typede l’action reçue, généralement via une structureswitch. - Mise à jour immuable : Pour chaque type d’action, il calcule et retourne un nouvel objet d’état. Si l’action ne correspond à aucun cas, il retourne l’état précédent inchangé.
Exemple :
javascript
const initialState = { value: 0, user: null };
function counterReducer(state = initialState, action) {
switch (action.type) {
case 'INCREMENT':
// Crée un nouvel objet avec value + 1 (copie immuable)
return { ...state, value: state.value + 1 };
case 'DECREMENT':
return { ...state, value: state.value - 1 };
case 'LOGIN':
return { ...state, user: action.payload };
default:
// Toujours retourner l'état inchangé pour une action inconnue
return state;
}
}
Pourquoi le reducer est-il une fonction pure ?
La pureté des reducers est ce qui rend Redux si puissant :
- Prévisibilité : Les changements d’état sont cohérents et faciles à anticiper.
- Débogage amélioré : Des outils comme Redux DevTools permettent d’annuler des actions (time-travel) ou de rejouer des séquences d’actions.
- Testabilité : Un reducer pur est trivial à tester : on lui donne un état et une action, on vérifie le nouvel état retourné .
- Sérialisation : L’état peut être sérialisé et rejoué plus tard, ce qui est utile pour le rendu serveur ou la persistance.
Tableau récapitulatif
| Concept | Définition | Rôle |
|---|---|---|
| Reducer | Fonction pure qui calcule le prochain état à partir de l’état précédent et d’une action. | C’est le cœur de la logique de mise à jour de Redux. |
| État précédent | L’état actuel de l’application avant le traitement de l’action. | Point de départ du calcul. |
| Action | L’objet décrivant ce qui s’est passé (avec un type et un payload). | Le déclencheur de la mise à jour. |
| Nouvel état | Le résultat du calcul, retourné de manière immuable. | Le nouvel état global de l’application. |
| Switch | Structure de contrôle souvent utilisée pour traiter différents types d’actions. | Permet de router l’action vers la bonne logique de mise à jour. |