useReducer pour les états complexes
Modélisez les transitions d’état avec une fonction de réduction, envoyez des objets d’action et préférez useReducer à useState lorsque la logique d’état devient complexe.
useReducer pour les états complexes est une leçon Frontend Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Frontend Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Frontend Academy comprend 4 leçons au total.
Quand useState ne suffit pas
Lorsque les transitions d'état impliquent une logique complexe, plusieurs valeurs liées ou des situations où le nouvel état dépend de manière non triviale de l'état précédent, useReducer constitue un choix plus clair que plusieurs appels à useState.
Modèle de fonction de réduction
Un réducteur est une fonction pure : (state, action) => newState. Il prend l'état actuel et un objet d'action, puis renvoie l'état suivant. Aucune mutation : renvoyez toujours un nouvel objet.
type Action =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'reset'; payload: number };
function counterReducer(state: number, action: Action): number {
switch (action.type) {
case 'increment': return state + 1;
case 'decrement': return state - 1;
case 'reset': return action.payload;
default: return state;
}
}Syntaxe de useReducer
useReducer(reducer, initialState) renvoie l'état actuel et une fonction de distribution. Appelez dispatch avec un objet d'action pour déclencher une transition d'état.
function Counter() {
const [count, dispatch] = useReducer(counterReducer, 0);
return (
<div>
<p>{count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset', payload: 0 })}>Reset</button>
</div>
);
}Actions typées — unions discriminées
Utilisez des types d'actions sous forme d'unions discriminées avec TypeScript afin d'obtenir une vérification exhaustive des types dans le switch du réducteur.
type CartAction =
| { type: 'ADD_ITEM'; item: CartItem }
| { type: 'REMOVE_ITEM'; id: string }
| { type: 'SET_QUANTITY'; id: string; qty: number }
| { type: 'CLEAR' };Exemple d'état complexe : panier d'achat
Un panier d'achat avec des opérations d'ajout, de suppression et de mise à jour des quantités constitue un cas d'utilisation idéal pour useReducer.
interface CartState {
items: CartItem[];
total: number;
}
function cartReducer(state: CartState, action: CartAction): CartState {
switch (action.type) {
case 'ADD_ITEM': {
const exists = state.items.find(i => i.id === action.item.id);
if (exists) {
const items = state.items.map(i =>
i.id === action.item.id ? { ...i, qty: i.qty + 1 } : i
);
return { ...state, items, total: calcTotal(items) };
}
const items = [...state.items, { ...action.item, qty: 1 }];
return { ...state, items, total: calcTotal(items) };
}
case 'CLEAR': return { items: [], total: 0 };
default: return state;
}
}La fonction de distribution est stable
La fonction dispatch est stable : elle ne change pas entre les rendus. Vous pouvez la transmettre en toute sécurité comme propriété ou l'utiliser comme dépendance de useEffect sans provoquer de nouvelles exécutions.
Combiner useReducer et useContext
Un modèle puissant : un contexte fournit à la fois l'état et la fonction de distribution, ce qui permet à tout consommateur de lire l'état ou de distribuer des actions sans transmettre les propriétés de proche en proche.
const CartContext = createContext<{ state: CartState; dispatch: Dispatch<CartAction> } | null>(null);
function CartProvider({ children }: { children: React.ReactNode }) {
const [state, dispatch] = useReducer(cartReducer, { items: [], total: 0 });
return <CartContext.Provider value={{ state, dispatch }}>{children}</CartContext.Provider>;
}useReducer ou useState
Choisissez useReducer lorsque l'état comporte plusieurs sous-valeurs, que l'état suivant dépend de manière complexe de l'état précédent, que les transitions sont nombreuses et nommées explicitement, ou lorsque vous souhaitez tester la logique d'état séparément du composant.
Tester les réducteurs isolément
Comme les réducteurs sont des fonctions pures, il est très simple de les tester sans afficher le moindre composant.
test('increment action increases count', () => {
expect(counterReducer(0, { type: 'increment' })).toBe(1);
expect(counterReducer(5, { type: 'increment' })).toBe(6);
});
test('reset action sets count to payload', () => {
expect(counterReducer(42, { type: 'reset', payload: 0 })).toBe(0);
});Immer pour les mises à jour immuables
La bibliothèque immer vous permet d'écrire du code qui semble modifier l'état, mais qui produit un nouvel état immuable. Elle est utile pour les mises à jour complexes d'objets imbriqués dans les réducteurs.
Vérification rapide
Quelle est la signature d'une fonction réductrice ?
Récapitulatif : useReducer
(état, action) => newState — pure, sans mutations. useReducer(réducteur, initial) renvoie [état, fonction de distribution]. Utilisez des types d'actions sous forme d'unions discriminées pour plus de sûreté. La fonction de distribution est stable. Cette solution convient parfaitement aux états complexes comportant de nombreuses transitions. Combinez-la avec useContext pour gérer l'état global. Testez les réducteurs séparément comme des fonctions pures.
Questions Fréquemment Posées
La leçon « useReducer pour les états complexes » est-elle gratuite ?
Oui — le texte complet de « useReducer pour les états complexes » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Frontend Academy, passe à CoddyKit PRO. Le cours Frontend Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « useReducer pour les états complexes » ?
Modélisez les transitions d’état avec une fonction de réduction, envoyez des objets d’action et préférez useReducer à useState lorsque la logique d’état devient complexe. Tu pratiques Frontend Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Frontend Academy ?
Aucune expérience préalable n'est requise. Frontend Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « useReducer pour les états complexes » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Frontend Academy ?
Oui. Chaque leçon Frontend Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- useContext pour l’état global
- useReducer pour les états complexes
- useMemo et useCallback pour les performances
- Hooks personnalisés : extraire une logique réutilisable