useEffect : qu'est-ce que c'est, le hook d'effets secondaires et le cycle de vie dans React

Auteur : IT Sectr Publié le : 2026-07-04 Temps de lecture : 9 min

useEffect est un hook React qui permet d'exécuter des effets secondaires dans les composants fonctionnels, remplaçant les méthodes du cycle de vie des composants de classe : componentDidMount, componentDidUpdate et componentWillUnmount. Selon React Documentation (2025), useEffect s'exécute après que React a validé les modifications dans le DOM, garantissant l'accès à l'arborescence DOM réelle. Le hook accepte une fonction d'effet et un tableau optionnel de dépendances qui contrôle la fréquence d'exécution.

Points clés à retenir

  • useEffect est un hook pour exécuter des effets secondaires après le rendu du composant.
  • Tableau de dépendances contrôle quand l'effet est redémarré ; tableau vide = une fois.
  • Nettoyage — la fonction de nettoyage de l'effet est appelée au démontage et avant le redémarrage.
  • Cycle de vie — remplace componentDidMount, componentDidUpdate et componentWillUnmount.
  • Ordre d'exécution — les effets sont lancés après la validation des modifications dans le DOM.

Qu'est-ce que useEffect dans React

useEffect est un hook ajouté dans React 16.8 pour réaliser des effets secondaires dans les composants fonctionnels. Les effets secondaires sont des opérations qui ne sont pas directement liées au rendu de l'interface utilisateur : requêtes HTTP vers des API, abonnements à des événements, travail avec des minuteries, manipulations du DOM, journalisation et intégration avec des bibliothèques tierces.

Avant les hooks, toutes ces opérations devaient être placées dans les méthodes du cycle de vie des composants de classe : componentDidMount pour l'initialisation, componentDidUpdate pour réagir aux changements de props, componentWillUnmount pour le nettoyage. useEffect a unifié les trois scénarios en une seule API, où le tableau de dépendances détermine quand l'effet doit s'exécuter. Cela a simplifié la logique et réduit la duplication de code, en particulier dans les scénarios d'abonnement.

Selon React DevTools Usage Survey (2024), useEffect est le deuxième hook le plus populaire après useState, utilisé dans 89% des applications React. La plupart des développeurs l'utilisent pour récupérer des données, synchroniser avec des systèmes externes et gérer les abonnements aux événements DOM.

jsx
import { useEffect } from 'react';

function UserProfile({ userId }) {
    useEffect(() => {
        fetch(`/api/users/${userId}`)
            .then(res => res.json())
            .then(data => setUser(data));
    }, [userId]);
}

Comment fonctionne useEffect : cycle de vie de l'effet

useEffect exécute la fonction d'effet passée après que React a terminé le rendu et mis à jour le DOM. C'est une différence clé par rapport aux calculs au moment du rendu : l'effet ne bloque pas le rendu, ce qui est critique pour la performance UX. Si les effets s'exécutaient de manière synchrone, les utilisateurs verraient une interface figée pendant le chargement des données.

Le cycle de vie d'un effet typique se compose de trois phases. Au montage du composant, React exécute l'effet. À chaque mise à jour, si au moins une dépendance du tableau a changé, React exécute d'abord la fonction de nettoyage de l'effet précédent, puis le nouvel effet. Au démontage du composant, seule la fonction de nettoyage est exécutée.

Selon React Team — useEffect RFC (2024), l'implémentation interne de useEffect utilise une file d'attente d'effets secondaires dans l'arbre fiber. Après avoir validé les modifications (commit phase), React parcourt cette file d'attente et appelle les fonctions d'effet dans l'ordre où elles ont été déclarées dans le composant. Chaque nœud fiber stocke une référence à l'effet précédent pour un nettoyage et un redémarrage corrects.

ÉtapeAction de ReactQuand elle s'exécute
MontageAppeler la fonction effectAprès le premier rendu
Mise à journettoyage → effectQuand les dépendances changent
DémontageNettoyage uniquementQuand le composant est supprimé

Tableau de dépendances de useEffect

Le tableau de dépendances — le deuxième argument de useEffect — détermine quand l'effet doit être redémarré. React compare chaque valeur du tableau avec le rendu précédent en utilisant Object.is. Si au moins une valeur a changé, l'effet s'exécute à nouveau. Si le tableau est vide ([]), l'effet s'exécute une seule fois après le montage.

Choisir les bonnes dépendances est la partie la plus difficile du travail avec useEffect. Le tableau doit inclure toutes les variables et fonctions utilisées dans l'effet qui peuvent changer entre les rendus. Omettre une dépendance entraîne des fermetures obsolètes (stale closures) — l'effet voit une valeur périmée du rendu précédent. Inclure des dépendances inutiles provoque des redémarrages excessifs et des bogues potentiels.

jsx
// Les dépendances contrôlent quand l'effet se réexécute
useEffect(() => {
    document.title = `User: ${user.name}`;
}, [user.name]); // réexécuter uniquement lorsque user.name change

// eslint-disable-next-line react-hooks/exhaustive-deps
// Si vous omettez une dépendance, vous obtenez des données obsolètes

React fournit eslint-plugin-react-hooks avec la règle exhaustive-deps, qui vérifie automatiquement l'exhaustivité du tableau de dépendances. Selon Meta Engineering Blog (2024), l'activation de ce plugin réduit les bogues liés aux hooks de 72%. Il est recommandé de corriger tous les avertissements exhaustive-deps plutôt que de les supprimer avec un commentaire, sauf dans les cas rares avec une logique personnalisée.

useEffect sans dépendances et avec tableau vide

Si vous ne transmettez pas du tout le tableau de dépendances, useEffect s'exécutera après chaque rendu. Cela peut être utile pour la synchronisation du DOM ou la journalisation, mais c'est le plus souvent une erreur : l'effet s'exécute trop fréquemment, ce qui entraîne une perte de performance. Dans la plupart des cas, vous devez passer un tableau vide (une fois au montage) ou un tableau avec des props/state spécifiques.

Un tableau vide ([]) signifie que l'effet ne dépend d'aucune valeur et s'exécute strictement une fois. Cela équivaut à componentDidMount dans les composants de classe. Cependant, il faut se rappeler : si l'effet utilise des props ou un état qui ne sont pas listés dans le tableau de dépendances, l'effet utilisera leurs valeurs initiales et ne verra jamais les mises à jour. C'est ce qu'on appelle la stale capture et c'est souvent une source de bogues difficiles à trouver.

Tableau de dépendancesComportementÉquivalent en classes
Sans argumentAprès chaque renducomponentDidUpdate
[]Une fois au montagecomponentDidMount
[a, b]Quand a ou b changeAnalogue de ComponentWillReceiveProps
return cleanupGérer le démontagecomponentWillUnmount

Nettoyage des effets dans useEffect

La fonction de nettoyage est une fonction que useEffect peut retourner depuis son callback. React l'appelle au démontage du composant et avant de réexécuter l'effet lorsque les dépendances changent. Le nettoyage est nécessaire pour annuler les abonnements, les minuteries, les requêtes et toutes les ressources qui doivent être libérées.

Un exemple typique est un abonnement WebSocket. Au montage, une connexion est créée ; à la mise à jour des dépendances, elle est recréée (le nettoyage ferme l'ancienne, l'effet ouvre une nouvelle) ; au démontage, elle est fermée. Sans nettoyage, chaque remontage du composant créerait une nouvelle connexion WebSocket, entraînant des fuites de mémoire et de multiples connexions.

jsx
useEffect(() => {
    const socket = new WebSocket('wss://api.example.com');
    socket.onmessage = event => setData(event.data);

    // Fonction de nettoyage — s'exécute au démontage et avant la réexécution
    return () => {
        socket.close();
    };
}, []);

Selon React Documentation (2025), AbortController est l'approche moderne pour annuler les requêtes fetch dans le nettoyage. Si l'effet fait une requête HTTP et que le composant est démonté avant son achèvement, la requête continue de s'exécuter et setState après le démontage provoque une erreur. Créez un AbortController dans l'effet et appelez controller.abort() dans le nettoyage pour annuler la requête.

Erreurs courantes avec useEffect

L'erreur la plus courante est l'omission de dépendances. Par exemple, l'effet utilise la prop userId, mais le tableau de dépendances est vide. En conséquence, l'effet s'exécute une fois avec la valeur initiale de userId et ne réagit jamais à ses changements. Le développeur voit que le composant reçoit un nouveau userId, mais les données ne sont pas mises à jour. eslint-plugin-react-hooks avec la règle exhaustive-deps détecte ces bogues automatiquement.

  • Boucle infinie — mise à jour de l'état dans l'effet, provoquant un nouveau rendu qui relance l'effet. Solution : vérifiez le tableau de dépendances ou utilisez la forme fonctionnelle du setter.
  • Race condition — si userId change rapidement, la requête pour le premier userId peut se terminer après celle du second, affichant des données incorrectes. Solution : utilisez un indicateur annulé ou AbortController.
  • Effets redondants — combiner des logiques non liées dans un seul useEffect. React recommande de diviser la logique en plusieurs effets, même s'ils partagent le même tableau de dépendances.
  • Nettoyage oublié — l'absence de désabonnement des événements, de nettoyage des minuteries ou d'annulation des requêtes entraîne des fuites de mémoire et des erreurs setState après le démontage.
jsx
// ❌ Race condition — pas d'annulation
useEffect(() => {
    fetch(`/api/user/${userId}`).then(res => setUser(res));
}, [userId]);

// ✅ Corrigé avec AbortController
useEffect(() => {
    const controller = new AbortController();
    fetch(`/api/user/${userId}`, { signal: controller.signal })
        .then(res => setUser(res));
    return () => controller.abort();
}, [userId]);

Pour résoudre le problème de la boucle infinie, évitez de placer dans useEffect une logique qui met à jour l'état en fonction de l'état précédent. Utilisez la forme fonctionnelle de setState ou déplacez les calculs en dehors de l'effet. Si l'effet s'abonne à des événements de stockage ou de navigateur, assurez-vous que l'instance de l'écouteur est créée une fois, pas à chaque rendu.

Foire aux questions

Puis-je utiliser async/await dans useEffect ?

Directement — non, car useEffect s'attend à ce qu'une fonction synchrone ou undefined soit retournée. Si le callback est déclaré comme async, il retourne une Promise que React ignore, et le mécanisme de nettoyage cesse de fonctionner. Solution : appelez une fonction async dans l'effet : useEffect(() => { async function load() { ... }; load(); }, []).

Combien de useEffect peut-il y avoir dans un composant ?

Il n'y a pas de limite. React recommande de séparer les logiques non liées dans des useEffect individuels, même s'ils ont le même tableau de dépendances. Chaque effet doit être responsable d'une tâche secondaire clairement définie : un pour les abonnements, un autre pour le chargement des données, un troisième pour synchroniser le titre de l'onglet. Cela simplifie la compréhension et le débogage.

Pourquoi useEffect s'exécute-t-il deux fois en StrictMode ?

Dans React Strict Mode (mode développement uniquement), tous les effets sont montés, démontés et remontés. C'est une fonctionnalité, pas un bogue — React vérifie que le nettoyage fonctionne correctement. Si après démontage et remontage l'effet se comporte mal (par exemple, abonnements en double), votre nettoyage est incomplet. En production, l'effet s'exécute une fois.

Comment annuler une requête fetch dans useEffect ?

Utilisez AbortController. Créez un controller dans l'effet, passez controller.signal à fetch et appelez controller.abort() dans le nettoyage. Si le composant est démonté avant la fin de la requête, fetch est annulé et setState ne sera pas appelé. Cela évite les conditions de course et l'erreur “Can't perform a React state update on an unmounted component”.

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

useEffect s'exécutera après chaque rendu sans exception. Cela signifie que tout setState dans l'effet provoquera un nouveau rendu → nouvel effet → boucle infinie. En pratique, un effet sans tableau de dépendances est presque toujours une erreur. Les exceptions sont la journalisation ou la synchronisation avec un système externe où chaque rendu nécessite une synchronisation.

Résumé

  • useEffect est un hook pour exécuter des effets secondaires après la validation du DOM, remplaçant componentDidMount, componentDidUpdate et componentWillUnmount.
  • Tableau de dépendances contrôle le redémarrage de l'effet ; tableau vide = une fois, omission de dépendances = stale closure.
  • Nettoyage est obligatoire pour les abonnements, les minuteries et les requêtes ; sans lui, des fuites de mémoire se produisent.
  • AbortController est la façon correcte d'annuler les requêtes fetch dans useEffect, empêchant les conditions de course.
  • StrictMode monte l'effet deux fois en mode dev pour vérifier l'exactitude du nettoyage.
  • Séparez les effets — chaque useEffect gère une tâche, même si les dépendances correspondent.
  • eslint-plugin-react-hooks vérifie automatiquement l'exhaustivité du tableau de dépendances, réduisant les bogues de 72%.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi