Menu

Cycle de vie d'un composant React : montage, mise à jour

Chaque composant React se monte (apparaît), se met à jour (refait son rendu) et se démonte (est retiré). Découvrez à quoi correspond chaque phase avec useEffect, les méthodes de cycle de vie des classes et leurs équivalents en hooks, ainsi que les phases de rendu et de commit.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Le cycle de vie d'un composant React comporte trois phases : le montage (le composant apparaît à l'écran pour la première fois), la mise à jour (il refait son rendu parce que son état, ses props ou son contexte ont changé) et le démontage (il est retiré). Dans les composants fonctions, vous réagissez à ces phases avec useEffect : un effet avec [] s'exécute après le montage, un effet avec des dépendances s'exécute après les mises à jour où elles ont changé, et la fonction renvoyée par un effet s'exécute au démontage.

La console sous l'aperçu montre chaque phase au moment où elle se produit.

La console commence par render, count = 0 et mounted. Chaque clic sur Count affiche un rendu et une mise à jour. Unmount affiche unmounted ; Mount again recommence depuis count = 0, car l'état a été jeté avec le composant.

Le montage

Un composant se monte la première fois que React fait son rendu à un endroit donné de l'arbre. React appelle la fonction, crée les nœuds DOM à partir du JSX qu'elle renvoie, les insère, laisse le navigateur afficher la page, puis exécute les effets du composant.

useEffect(fn, []) est l'endroit où démarrer ce qui doit exister tant que le composant est à l'écran : un abonnement, un minuteur, une connexion, une première requête de données. Il s'exécute après l'affichage, il ne retarde donc jamais la première image.

La mise à jour

Un composant se met à jour (refait son rendu) quand :

  • son propre état change,
  • son parent refait son rendu (par défaut, chaque enfant refait aussi le sien, que ses props aient changé ou non),
  • un contexte qu'il lit change.

Après chaque mise à jour, React exécute les effets dont les dépendances ont changé. Avant de relancer un effet, il exécute le nettoyage précédent de cet effet, donc l'ancien abonnement est fermé avant que le nouveau s'ouvre. La page sur le rendu détaille ce qui déclenche un rendu.

Le démontage

Un composant se démonte quand son parent cesse de l'afficher (comme {show && <Counter />} le fait ci-dessus), quand sa key change, ou quand la racine elle-même est démontée. React retire ses nœuds DOM, exécute le nettoyage de chaque effet et jette son état. Si le composant réapparaît plus tard, c'est une instance toute neuve.

Parents et enfants

React fait le rendu de haut en bas mais exécute les effets de bas en haut. Quand un parent et un enfant se montent ensemble, les effets de l'enfant s'exécutent en premier, donc l'effet d'un parent peut compter sur des enfants entièrement mis en place.

Le montage affiche render Parent, render Child, Child effect, Parent effect. Appuyez sur Remove et les nettoyages s'exécutent dans l'ordre inverse : Parent cleanup, puis Child cleanup.

Phases de rendu et de commit

Chaque mise à jour passe par deux phases :

  1. Phase de rendu. React appelle vos composants pour calculer le nouveau JSX et le compare au résultat précédent. Rien ne change encore à l'écran. React peut mettre ce travail en pause, l'exécuter deux fois en StrictMode ou le jeter, c'est pourquoi le rendu doit être pur : pas de requêtes, pas d'abonnements, pas de modification de variables extérieures.
  2. Phase de commit. React applique les différences au DOM, attache les refs et exécute les callbacks de useLayoutEffect, tout cela avant que le navigateur affiche la page. Les callbacks de useEffect s'exécutent ensuite, généralement une fois que le navigateur a affiché la page. Quand un clic ou une autre entrée discrète a causé la mise à jour, React les exécute plutôt juste après les effets de layout, pour que le résultat soit prêt avant l'événement suivant.

Chaque clic affiche les trois lignes dans le même ordre. Ces effets n'ont pas de tableau de dépendances, ils s'exécutent donc après chaque rendu. Ajoutez [] comme second argument aux deux et ils ne s'exécutent qu'après le premier.

Méthodes de cycle de vie des classes et leurs équivalents en hooks

Les composants classes détaillent le cycle de vie sous forme de méthodes nommées. Vous les rencontrerez dans du code ancien et dans les error boundaries, qui ont toujours besoin d'une classe.

Méthode de classeQuand elle s'exécuteÉquivalent dans un composant fonction
constructorune fois, avant le premier renduuseState(initial), useRef
static getDerivedStateFromPropsavant chaque renducalculer la valeur pendant le rendu, ou réinitialiser avec une key
renderà chaque rendule corps de la fonction
componentDidMountaprès l'insertion du premier rendu dans le DOMuseEffect(fn, [])
shouldComponentUpdateavant une mise à jour, peut la sauterReact.memo (il renvoie la réponse inverse : « les props sont-elles égales »)
getSnapshotBeforeUpdatejuste avant la modification du DOMpas de hook direct ; useLayoutEffect avec une ref est le plus proche
componentDidUpdateaprès chaque mise à jouruseEffect(fn, [deps]) (s'exécute aussi après le montage)
componentWillUnmountavant le retraitle nettoyage renvoyé par useEffect
getDerivedStateFromError, componentDidCatchquand un enfant lève une erreuraucun : écrivez une classe error boundary

Voici une classe qui affiche chaque méthode au moment où elle s'exécute :

Le montage affiche constructor, getDerivedStateFromProps, render, componentDidMount. Un clic affiche getDerivedStateFromProps, shouldComponentUpdate, render, getSnapshotBeforeUpdate, componentDidUpdate. Faites renvoyer false à shouldComponentUpdate et les clics cessent de mettre à jour le bouton : l'état change, mais React saute le rendu. La page sur les composants classes montre comment convertir une classe comme celle-ci en fonction.

Pensez synchronisation, pas cycle de vie

Le tableau des hooks est utile pour lire du code ancien, mais il peut vous pousser à écrire des effets qui copient les habitudes des classes, comme un gros effet « monté » et un gros effet « mis à jour ». Un effet se lit mieux comme « garder cette chose extérieure synchronisée avec ces valeurs » : se connecter à roomId, et quand roomId change, se déconnecter puis se reconnecter. Écrivez un effet par chose à synchroniser, listez les valeurs qu'il utilise comme dépendances, et laissez React décider quand l'exécuter.

Questions fréquentes

Quelles sont les phases du cycle de vie d'un composant React ?

Le montage (React crée le composant et place son résultat à l'écran), la mise à jour (il refait son rendu parce que son état, ses props ou son contexte ont changé) et le démontage (il est retiré et fait son nettoyage).

Quel est l'équivalent en hook de componentDidMount ?

useEffect(() => { ... }, []). Le tableau de dépendances vide fait qu'il s'exécute une seule fois, après l'affichage du premier rendu. La fonction qu'il renvoie est l'équivalent de componentWillUnmount.

Quel est l'équivalent en hook de componentDidUpdate ?

useEffect avec les valeurs qui vous intéressent dans le tableau de dépendances, comme [userId]. Contrairement à componentDidUpdate, il s'exécute aussi après le premier rendu, il couvre donc à la fois le montage et la mise à jour.

Dans quel ordre s'exécutent les effets du parent et de l'enfant ?

React fait le rendu du parent vers le bas, mais exécute les effets des enfants vers le haut : l'effet d'un enfant s'exécute avant celui de son parent. Au démontage, le nettoyage du parent s'exécute avant celui de l'enfant.

Que sont les phases de rendu et de commit ?

Pendant la phase de rendu, React appelle vos composants pour déterminer à quoi l'écran doit ressembler ; il peut mettre ce travail en pause ou le jeter. Pendant la phase de commit, il applique les changements au DOM et exécute les effets de layout ; les effets ordinaires s'exécutent ensuite, généralement une fois que le navigateur a affiché la page.

Illustration des langages de programmation de Coddy

Apprendre à coder avec Coddy

COMMENCER