aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Développement Web

Hook useEffect de React : guide d'utilisation pratique

Le hook useEffect de React connecte vos composants au monde extérieur à React — requêtes réseau, abonnements, minuteurs, API du navigateur. Il est puissant, mais utilisé sans soin il produit des boucles infinies, des fuites de mémoire et des comportements « fantômes » difficiles à déboguer. Ce guide couvre le tableau de dépendances, la logique de nettoyage et les erreurs les plus fréquentes, avec de vrais exemples.

À quoi sert useEffect

Un effet est un effet de bord qui s'exécute après le rendu. React dessine d'abord l'écran, puis exécute votre effet. Cela rend les effets adaptés au travail qui dialogue avec l'extérieur et n'influence pas directement le rendu :

  • Récupérer des données depuis un serveur (fetch, axios)
  • Mettre en place un WebSocket ou un abonnement à des événements
  • Démarrer un setInterval / setTimeout
  • Mettre à jour le titre du document ou des API du navigateur

Si vous calculez seulement une valeur à partir d'une autre, vous n'avez pas besoin d'effet — faites-le pendant le rendu. Un effet est nécessaire quand vous touchez à quelque chose en dehors du rendu.

Le tableau de dépendances : le cœur du sujet

useEffect se comporte de trois façons, et la différence tient au second argument, le tableau de dépendances :

// 1) S'exécute après chaque rendu
useEffect(() => {
  console.log('chaque rendu');
});

// 2) S'exécute uniquement au premier montage
useEffect(() => {
  console.log('une fois');
}, []);

// 3) S'exécute chaque fois que userId change
useEffect(() => {
  fetchUser(userId);
}, [userId]);

La règle est simple : toute valeur réactive (prop, state, fonction) que vous utilisez dans l'effet doit figurer dans le tableau de dépendances. Omettre une dépendance fait s'exécuter l'effet avec des valeurs périmées. L'eslint-plugin-react-hooks de l'équipe React fournit une règle exhaustive-deps qui détecte cela pour vous ; corrigez la cause racine plutôt que de masquer l'avertissement.

La fonction de nettoyage et les fuites de mémoire

Si un effet met en place quelque chose de persistant (un abonnement, un minuteur, un écouteur), vous êtes aussi responsable de le démonter. La fonction que vous retournez depuis l'effet s'exécute avant que le composant ne soit retiré du DOM et avant que l'effet ne s'exécute à nouveau :

useEffect(() => {
  const id = setInterval(() => {
    setSeconds((s) => s + 1);
  }, 1000);

  return () => clearInterval(id); // nettoyage
}, []);

Sans nettoyage, chaque ré-exécution empile un nouveau setInterval qui continue à se déclencher même après le démontage du composant — une fuite de mémoire classique. La même règle s'applique aux écouteurs d'événements :

useEffect(() => {
  const onResize = () => setWidth(window.innerWidth);
  window.addEventListener('resize', onResize);
  return () => window.removeEventListener('resize', onResize);
}, []);

Situations de concurrence (race conditions)

Un piège fréquent lors de la récupération de données : si l'utilisateur passe rapidement d'un enregistrement à l'autre, une requête plus ancienne peut se résoudre tardivement et écraser les données les plus récentes. Évitez-le avec un drapeau (ou un AbortController) dans le nettoyage :

useEffect(() => {
  let active = true;
  fetch(`/api/users/${userId}`)
    .then((r) => r.json())
    .then((data) => {
      if (active) setUser(data);
    });
  return () => {
    active = false; // la requête périmée ne met plus à jour le state
  };
}, [userId]);

Dans les navigateurs modernes, annuler réellement la requête avec AbortController est plus propre. Dans les grandes applications, des bibliothèques comme TanStack Query ou SWR gèrent ces situations de concurrence et la mise en cache à votre place.

Les erreurs les plus fréquentes

  • Omettre une dépendance : les valeurs laissées hors du tableau se figent (stale closure). Solution : suivez la règle exhaustive-deps.
  • Boucle infinie avec un tableau vide : le vrai problème est souvent l'inverse — placer dans le tableau un objet/tableau/fonction recréé à chaque rendu redéclenche l'effet sans fin. Stabilisez-les avec useMemo / useCallback.
  • Mettre des données dérivées dans un effet : n'utilisez pas d'effet pour calculer un state à partir d'un autre ; calculez-le pendant le rendu.
  • Oublier le nettoyage : écrivez un démontage pour chaque abonnement/minuteur.
  • Passer une fonction async directement : useEffect(async () => …) est incorrect ; l'effet doit retourner une fonction de nettoyage, pas une Promise. Définissez et appelez une fonction async séparée à l'intérieur.

Pourquoi StrictMode exécute-t-il l'effet deux fois ?

En développement, React 18+ sous StrictMode monte délibérément chaque effet une fois, le démonte immédiatement, puis le remonte. Le but est de révéler si votre nettoyage est correctement écrit. Ne paniquez pas en croyant à un « bug » quand votre effet se déclenche deux fois ; si vous écrivez le nettoyage correctement, ce comportement est inoffensif et ne se produit pas dans une build de production.

Questions fréquentes

Quelle est la différence entre useEffect et useLayoutEffect ?

useEffect s'exécute de façon asynchrone après que le navigateur a terminé le rendu visuel ; c'est le bon choix dans la plupart des cas. useLayoutEffect s'exécute de façon synchrone après la mise à jour du DOM mais avant le paint ; ne l'utilisez que lorsque vous devez mesurer et ajuster la mise en page immédiatement (par exemple positionner une infobulle), sinon il peut nuire aux performances.

Que se passe-t-il si je ne passe jamais de tableau de dépendances ?

Si vous omettez entièrement le second argument, l'effet s'exécute après chaque rendu. C'est rarement souhaité et signifie généralement que vous vouliez écrire [] ou les vraies dépendances.

Un effet est-il la meilleure façon de récupérer des données ?

Pour de petits cas, oui, mais des bibliothèques comme TanStack Query ou SWR constituent un choix plus solide pour la plupart des projets car elles gèrent automatiquement la mise en cache, les nouvelles tentatives et les situations de concurrence.

Les effets sont-ils devenus incontrôlables dans votre architecture React ? Passons en revue vos composants pour nettoyer les stale closures et les fuites. Contactez-moi et nous renforcerons votre projet ensemble.

Bu kategorideki tüm yazılar →

Devamı için