Revisiter l’utilisation des crochets du cycle de vie des composants de React en prévision du rendu asynchrone

Si vous avez consulté la documentation ou surveillé les conseils de l’équipe centrale de React, vous avez probablement lu que vous ne devriez pas gérer les souscriptions ni les effets secondaires dans le constructeur ou composantWillMount.

Bien que l’avis soit clair, le raisonnement qui sous-tend ces instructions n’a pas été beaucoup expliqué, même si ce n’est pas sans raison. La brève explication est que les détails d’implémentation du rendu asynchrone de Fiber, qui motivent ces instructions, ne sont pas entièrement réglés.

Le rendu asynchrone de Fibre n’étant pas encore activé, le fait d’ignorer une partie de la sagesse relative à l’utilisation du cycle de vie n’a peut-être pas encore fait mouche. Cela pourrait changer à l’avenir et c’est ce que nous allons explorer dans cet article.

Précision: la fibre est-elle prête?

Si le rendu asynchrone de Fibre n’est pas prêt, vous vous demandez peut-être si l’équipe vous a vendu un compte à rebours contrefait. Rassurez-vous, ce n'est pas le cas. Le nouveau moteur de Fibre, ou plus précisément le processus de rapprochement, a été mis en service avec React v16. Cela dit, nous ne pouvons pas passer du rendu synchrone au rendu hiérarchisé pour le moment.

Comment l'utilisation des cycles de vie sera-t-elle impactée?

En conclusion, nous ne le savons pas tant que le rendu asynchrone n’est pas figé. Sinon, l'équipe de React l'aurait dit. Mais nous pouvons tirer des conclusions sûres sur le traitement des abonnements et des effets secondaires. Et c’est ce que nous allons explorer.

Par souci de simplicité, voici un exemple d’abonnement à une liste de requêtes multimédia dans le constructeur, qui ne nous posera pas actuellement de problèmes:

Avant que le rendu async ne soit activé, nous n’avons aucun problème, car nous pouvons apporter les garanties suivantes concernant le composant:

  1. Le constructeur sera suivi de manière synchrone par composantWillMount, si nous décidons de l'utiliser, puis de le rendre. Surtout, nous ne serons pas interrompus avant le rendu. De ce fait, nous pouvons garantir davantage…
  2. Si le composant ne se monte plus, composantWillUnmount nettoie au préalable l'écouteur d'événements (abonnement). Cela signifie que la fenêtre ne conservera pas de référence à la méthode handleMediaEvent du composant via la liste de requêtes de supports, ce qui permettra au composant non monté d’être nettoyé et d’éviter une fuite de mémoire. Ne pas résoudre ce problème une fois pour toutes ne serait pas un problème, mais un ré-assemblage de composant et l'ajout de plus d'auditeurs pourraient poser des problèmes tout au long de la durée de vie de l'application.
Il y a une mise en garde: les limites d'erreur. Je vais en parler un peu plus tard.

Alors, quels changements avec le rendu asynchrone?

Pour aller droit au but: de nombreuses méthodes du cycle de vie de votre composant de classe peuvent être déclenchées plusieurs fois. En effet, le processus de rapprochement de Fiber permet à React d’obtenir le travail qu’il accomplit. Permettre au thread principal de gérer quelque chose qui doit être affiché de manière urgente, comme une animation. Cela peut impliquer le rejet du travail déjà terminé, y compris éventuellement des appels du constructeur, composantWillMount, rendu, composantWillUpdate et composantWillReceiveProps.

Mais composantDidUpdate et composantDidMount ne sont appelés que lorsque React a vidé les modifications apportées à son environnement hôte. Évitant ainsi ces problèmes. Le nettoyage ou le démontage de composantWillUnmount doit refléter la configuration de composantDidMount. Assurer l'échec de l'appel de ce raccordement ne sera pas problématique.

Nous devons donc gérer les souscriptions et les effets secondaires dans composantDidMount. Les effets secondaires se produisant dans le constructeur et composantWillMount incluent le plus souvent des requêtes réseau. Il est particulièrement difficile d’appeler plusieurs fois lorsque cela entraîne des mutations dans les magasins de données de notre application.

Une dernière note.

Comme moi, vous avez peut-être supposé que le tout premier rendu de React était toujours synchrone. Mais ce n'est pas nécessairement le cas!

Brian Vaughn (qui fait partie de l'équipe principale de React) m'a informé que l'intention actuelle est de synchroniser le premier rendu par défaut, l'option optionnelle étant asynchrone. Il a ajouté qu’un premier rendu de priorité basse pourrait être utile si, par exemple, le conteneur hôte de React n’était pas encore prêt. Évidemment, ceci est plus applicable lorsque votre corps HTML est constitué de plus d’une div unique pour que React rende le rendu.

Pour une liste de contrôle visuelle de ce qui peut être effectué en toute sécurité et où, consultez l’essentiel de Brian.

À quoi sert composantWillMount?

Le cas d'utilisation est très étroit. Les développeurs citent souvent deux caractéristiques souhaitables de composantWillMount. Elles sont:

  1. setState peut être appelé à partir de composantWillMount, contrairement au constructeur.
  2. Une valeur setState dans componentWillMount ne causera pas deux rendus si elle se produit de manière synchrone, avant le rendu, contrairement à composantDidMount.

De même, la raison pour laquelle composantWillMount a été conservée dans la base de code, comme l'explique Sebastian Markbåge dans une proposition visant à déconseiller composantWillMount, était de gérer un effet secondaire qui pourrait être synchrone (si un cache local contenait les données souhaitées) ou asynchrone. De nos jours, comme le dit son bloc de code de démonstration, getInitialState, les constructeurs de classe es6 et les initialiseurs de propriétés es7 répondent à cet objectif.

Cela dit, une requête GET en lecture seule initiée à partir de composantWillMount peut être utile. Sur un appareil à rendu lent, par exemple un mobile moyen, il est possible de gagner quelques centaines de millisecondes en lançant la demande ici plutôt que composantDidMount. Bien entendu, une telle requête doit être idempotente / en lecture seule, car elle peut être déclenchée plusieurs fois.

ComponentWillMount est toujours la seule méthode de cycle de vie appelée autre que le constructeur lors du rendu sur le serveur. Il est donc possible qu'il existe quelques cas d'utilisation. N'ayant pas essayé moi-même le rendu côté serveur, je ne peux pas en dire beaucoup sur le sujet.

Ces avertissements ne sont-ils donc pertinents que lorsque le rendu asynchrone est actif?

Comme Brian m'a fait remarquer, pas tout à fait. Les limites d'erreur, mises en production avec React v16, peuvent également entraîner l'appel de composantWillMount et de composantWillUpdate sans composantDidMount et composantDidUpdate!

Y a-t-il d'autres changements dont il faut se méfier?

React a récemment lancé un processus RFC (Request For Comment), permettant à la communauté plus large de discuter des idées. Deux des premiers RFC proviennent de membres de l'équipe principale de React et discutent de changements potentiels importants.

  1. Andrew Clark a soumis une RFC sur les modifications apportées à l'API de contexte. Cela, espérons-le, soulagera un peu la difficulté de se déplacer si CompomponentUpdate lors de la tentative de diffusion de l'état dans l'arborescence des composants. Le RFC est ici.
  2. Brian a soumis une RFC pour les crochets statiques à cycle de vie sûrs et asynchrones. Cela implique principalement la dépréciation progressive de composantWillMount, de composantWillUpdate et de composantWillReceieveProps. Deux nouveaux crochets statiques sont proposés: prefetch et deriveStateFromProps. Vous pouvez lire plus de la proposition ici, et le RFC ici. J'espère que cet article vous a fourni une bonne idée de la raison pour laquelle ces changements sont proposés :).
  3. Dans la proposition susmentionnée, Brian a également annoncé une nouvelle RFC pour un nouveau raccord SSR: composantDidServerRender, qui remplace ComponentWillMount sur le serveur.

Gardez à l'esprit qu'il s'agit de premières propositions!

A propos de l'auteur

Je suis un développeur australien basé à Adélaïde, passionné par le développement front-end et back-end avec JavaScript! J'ai récemment publié ma première bibliothèque open source pour React: React-MQL-Manager. Voici une démonstration simple, intégrant React Router v4 pour un routage réactif!

Je suis actuellement à la recherche de ma première position en front-end ou full-stack. Vous pouvez me joindre par courrier électronique ou me saluer sur Twitter: @awebofbrown.

Remerciement spécial

Un grand merci à Brian Vaughn, de l'équipe principale de React, pour avoir pris le temps de lire un brouillon de l'article ainsi que pour ses suggestions et corrections. En plus de travailler sur React, Brian est l'auteur de superbes bibliothèques à code source libre telles que React-Virtualized et JS-Search, ainsi que de l'aide pour répondre aux questions de la communauté sur des forums tels que StackOverflow.