Retour à l'accueil

Comment utiliser les Hooks React : Guide complet avec exemples

Ce guide complet apprend aux développeurs comment utiliser efficacement les hooks React dans les applications React modernes. Il couvre les hooks intégrés essentiels comme useState et useEffect, explique les règles des hooks, fournit des techniques d'optimisation des performances avec useMemo et useCallback, et montre comment créer des hooks personnalisés avec des exemples de code pratiques.

Tutoriel sur les Hooks React : Maîtrisez l'état et les effets en 2026
Advertisement 728x90

Comment utiliser les Hooks React : Guide complet avec exemples

Comment utiliser les Hooks React : Guide complet avec exemples

Quand React 16.8 a introduit les Hooks début 2019, cela a fondamentalement changé la façon dont les développeurs construisent des applications React en permettant aux composants fonctionnels de gérer l'état, les effets de bord et le contexte sans écrire de composants de classe. Comprendre comment utiliser les Hooks React est désormais essentiel pour tout développeur React moderne, car les Hooks sont devenus « la seule façon dont la plupart du code React est écrit ». Ce guide vous présentera les Hooks intégrés essentiels, expliquera les règles qui les régissent et fournira des exemples pratiques que vous pourrez utiliser immédiatement.

Ce que vous allez apprendre

À la fin de ce guide, vous utiliserez avec confiance les Hooks principaux de React — useState, useEffect, useContext, useRef, useReducer, useMemo et useCallback — dans vos propres projets. Vous comprendrez quand choisir un Hook plutôt qu'un autre, comment éviter les pièges courants comme les rendus inutiles, et comment extraire la logique réutilisable dans des Hooks personnalisés. Le point le plus important à retenir est que les Hooks ne sont que des fonctions — apprendre à les composer est la clé pour maîtriser React.

Google AdInline article slot

Comprendre les règles des Hooks

Avant de plonger dans les Hooks individuels, vous devez comprendre deux règles non négociables appliquées par le paquet eslint-plugin-react-hooks :

  1. Appelez les Hooks uniquement au niveau supérieur. N'appelez jamais de Hooks à l'intérieur de boucles, de conditions ou de fonctions imbriquées. React se base sur l'ordre dans lequel les Hooks sont appelés pour préserver l'état entre les rendus — si l'ordre change, React ne peut pas associer correctement l'état à son Hook.

  2. Appelez les Hooks uniquement depuis des fonctions React. Vous ne pouvez appeler des Hooks que depuis des composants fonctionnels ou depuis d'autres Hooks personnalisés. Une fonction JavaScript ordinaire ne peut pas appeler useState ou useEffect.

    Google AdInline article slot

Une convention découle de la deuxième règle : toute fonction qui appelle des Hooks doit commencer par use (par exemple, useCustomHook). Le linter utilise ce préfixe pour appliquer correctement les règles.

Les Hooks les plus essentiels que vous utiliserez quotidiennement

useState : Gérer l'état d'un composant

Le Hook useState est le Hook le plus fondamental, vous permettant d'ajouter un état aux composants fonctionnels. Il retourne un tableau avec deux éléments : la valeur actuelle de l'état et une fonction pour la mettre à jour.

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // L'état initial est 0
  
  return (
    <button onClick={() => setCount(count + 1)}>
      Cliqué {count} fois
    </button>
  );
}

Lors de la mise à jour de l'état basée sur la valeur précédente, utilisez la forme de mise à jour fonctionnelle pour éviter les conditions de concurrence, surtout avec le regroupement automatique de React :

Google AdInline article slot
// Sûr : utilise la valeur d'état précédente
setCount(prevCount => prevCount + 1);

// Également sûr pour les objets : étend l'état précédent
setUser(prevUser => ({ ...prevUser, name: 'Jane' }));

Si le calcul de l'état initial est coûteux, passez une fonction plutôt qu'une valeur — React ne l'exécutera que lors du rendu initial :

const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

useEffect : Gérer les effets de bord

Le Hook useEffect vous permet d'effectuer des effets de bord dans les composants fonctionnels, comme récupérer des données, configurer des abonnements ou modifier manuellement le DOM. Par défaut, les effets s'exécutent après chaque rendu terminé, mais vous pouvez contrôler quand ils se déclenchent en utilisant le tableau de dépendances.

import { useEffect, useState } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    // Cet effet s'exécute après le montage du composant et lorsque userId change
    fetchUser(userId).then(data => setUser(data));
    
    // Fonction de nettoyage optionnelle s'exécute avant le prochain effet et lors du démontage
    return () => {
      // Annulez les requêtes en attente ou nettoyez les abonnements
    };
  }, [userId]); // Tableau de dépendances : ne se réexécute que lorsque userId change

  return <div>{user?.name}</div>;
}

Modèles clés pour useEffect :

  • Tableau de dépendances vide [] : L'effet s'exécute une fois après le rendu initial (montage).
  • Pas de tableau de dépendances : L'effet s'exécute après chaque rendu (rarement ce que vous voulez).
  • Fonction de nettoyage : Empêche les fuites de mémoire en nettoyant les abonnements, les minuteurs ou les requêtes réseau en attente.

Avertissement important : Tous les changements d'état ne nécessitent pas un effet. Si vous pouvez calculer une valeur pendant le rendu, faites-le directement au lieu d'utiliser useEffect :

// ❌ Effet inutile
const [fullName, setFullName] = useState('');
useEffect(() => {
  setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);

// ✅ Calcul direct pendant le rendu
const fullName = `${firstName} ${lastName}`;

useContext : Consommer le contexte sans prop drilling

Le Hook useContext vous permet de lire les valeurs du contexte React sans envelopper votre composant dans un composant Consumer :

import { useContext } from 'react';

// Créer un contexte
const ThemeContext = React.createContext('light');

function ThemedButton() {
  // Lire la valeur du contexte directement
  const theme = useContext(ThemeContext);
  return <button className={theme}>Cliquez-moi</button>;
}

Lorsque la valeur du fournisseur de contexte change, tout composant utilisant useContext se rend automatiquement.

useRef : Référencer des valeurs qui ne déclenchent pas de rendus

Le Hook useRef crée un objet ref mutable dont la propriété .current persiste entre les rendus. Contrairement à l'état, la mise à jour d'une ref ne provoque pas de rendu. Cela rend les refs idéales pour :

  • Stocker des références d'éléments DOM
  • Garder la trace des identifiants de minuteurs
  • Persister des valeurs qui ne devraient pas déclencher de mises à jour de l'interface utilisateur
import { useRef, useEffect } from 'react';

function TextInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    // Focus sur l'input après le montage du composant
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} type="text" />;
}

useReducer : Gérer une logique d'état complexe

Pour un état qui implique plusieurs sous-valeurs ou des transitions complexes, useReducer est souvent préférable à useState. Il accepte une fonction réductrice et un état initial, retournant l'état actuel et une fonction de dispatch :

import { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return { count: action.payload };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  
  return (
    <>
      Compteur : {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <button onClick={() => dispatch({ type: 'reset', payload: 0 })}>Réinitialiser</button>
    </>
  );
}

Hooks d'optimisation des performances

useMemo : Mettre en cache des calculs coûteux

useMemo met en cache le résultat d'un calcul et ne le recalcule que lorsque les dépendances changent :

import { useMemo } from 'react';

function TodoList({ todos, filter }) {
  // Ne recalcule que lorsque todos ou filter changent
  const filteredTodos = useMemo(() => {
    return todos.filter(todo => todo.status === filter);
  }, [todos, filter]);

  return (
    <ul>
      {filteredTodos.map(todo => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  );
}

useCallback : Mémoiser les références de fonctions

useCallback retourne une version mémoisée d'une fonction de rappel qui ne change que si les dépendances changent. C'est particulièrement utile lors du passage de fonctions de rappel à des composants enfants optimisés qui reposent sur l'égalité de référence pour éviter des rendus inutiles :

import { useCallback } from 'react';

function ParentComponent() {
  const handleClick = useCallback(() => {
    console.log('Bouton cliqué');
  }, []); // La référence de la fonction reste stable entre les rendus

  return <ChildButton onClick={handleClick} />;
}

Hooks personnalisés : Réutiliser la logique entre les composants

La véritable puissance des Hooks émerge lorsque vous créez des Hooks personnalisés pour extraire et réutiliser la logique avec état. Un Hook personnalisé est simplement une fonction JavaScript dont le nom commence par use et qui peut appeler d'autres Hooks.

Exemple : useLocalStorage

Ce Hook personnalisé synchronise l'état avec localStorage, persistant les données entre les rechargements de page :

import { useState, useEffect } from 'react';

function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(() => {
    if (typeof window === 'undefined') return initialValue;
    const stored = localStorage.getItem(key);
    return stored !== null ? JSON.parse(stored) : initialValue;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
}

// Utilisation
function ThemeToggle() {
  const [theme, setTheme] = useLocalStorage('theme', 'light');
  return (
    <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
      Passer en mode {theme === 'light' ? 'sombre' : 'clair'}
    </button>
  );
}

Exemple : useMediaQuery

Ce Hook vous permet de rendre des composants de manière conditionnelle en fonction des requêtes média CSS, comme la préférence de l'utilisateur pour une animation réduite :

import { useState, useEffect } from 'react';

function useMediaQuery(query) {
  const [matches, setMatches] = useState(() => {
    if (typeof window === 'undefined') return false;
    return window.matchMedia(query).matches;
  });

  useEffect(() => {
    const mediaQueryList = window.matchMedia(query);
    const onChange = (event) => setMatches(event.matches);
    mediaQueryList.addEventListener('change', onChange);
    return () => mediaQueryList.removeEventListener('change', onChange);
  }, [query]);

  return matches;
}

// Utilisation
function MotionAwareComponent() {
  const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)');
  return prefersReducedMotion ? <StaticHero /> : <AnimatedHero />;
}

React 19 : Nouveaux Hooks pour les formulaires et les données asynchrones

React 19 (sorti en décembre 2024) a introduit plusieurs nouveaux Hooks conçus pour simplifier la gestion des formulaires et les opérations asynchrones.

useActionState : Simplifier la soumission de formulaires

useActionState gère l'état de soumission du formulaire, retournant le dernier résultat, une fonction d'action et un indicateur d'attente :

import { useActionState } from 'react';

async function subscribeAction(prevState, formData) {
  const email = formData.get('email');
  try {
    await subscribe(email);
    return { ok: true };
  } catch (error) {
    return { ok: false, error: error.message };
  }
}

function NewsletterForm() {
  const [state, formAction, isPending] = useActionState(
    subscribeAction,
    { ok: false }
  );

  return (
    <form action={formAction}>
      <input name="email" type="email" required />
      <button type="submit" disabled={isPending}>
        {isPending ? 'Abonnement en cours...' : "S'abonner"}
      </button>
      {state.ok && <p>Vous êtes abonné !</p>}
      {state.error && <p style={{ color: 'red' }}>{state.error}</p>}
    </form>
  );
}

useFormStatus : Accéder à l'état du formulaire parent

useFormStatus permet aux composants imbriqués de savoir si leur formulaire parent est en cours de soumission :

import { useFormStatus } from 'react';

function SubmitButton() {
  const { pending } = useFormStatus();
  return (
    <button type="submit" disabled={pending}>
      {pending ? 'Enregistrement...' : 'Enregistrer'}
    </button>
  );
}

Intégration avec Redux : Le Hook useSelector

Lors de l'utilisation de Redux avec React, le Hook useSelector est la méthode moderne et recommandée pour accéder à l'état depuis le store Redux. Il remplace l'ancien composant d'ordre supérieur connect et fonctionne mieux avec TypeScript.

import { useSelector, useDispatch } from 'react-redux';

function CounterComponent() {
  // Extraire des données spécifiques du store Redux
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

  return (
    <div>
      <span>{count}</span>
      <button onClick={() => dispatch(increment())}>Incrémenter</button>
    </div>
  );
}

Important : useSelector utilise par défaut une égalité de référence stricte ===. Retourner un nouvel objet à chaque fois forcera des rendus. Utilisez des sélecteurs mémoisés ou appelez useSelector plusieurs fois pour des champs individuels afin d'optimiser les performances :

// ❌ Cela provoque des rendus à chaque action
const { count, user } = useSelector((state) => ({
  count: state.count,
  user: state.user
}));

// ✅ Appelez useSelector pour chaque champ
const count = useSelector((state) => state.count);
const user = useSelector((state) => state.user);

Sources

  • Documentation officielle de React : Hooks React intégrés
  • Documentation officielle de React : Référence de l'API des Hooks
  • Documentation de React Redux : API des Hooks
  • Patterns.dev : Modèle des Hooks
  • Documentation officielle de React : Utilisation du Hook d'état

— Editorial Team

Advertisement 728x90

Lire ensuite