Les hooks de React sont une fonctionnalité apparue après la fibre, donc beaucoup de gens croient à tort que les hooks doivent s'appuyer sur la fibre pour être implémentés. En fait, ce n'est pas nécessairement le cas.
Désormais, les hooks ne sont pas seulement implémentés dans React, mais également dans des frameworks tels que Preact, React Ssr et Midway. Leur implémentation ne repose pas sur la fibre.
Voyons comment les hooks dans ces différents frameworks sont implémentés :
React décrit l'interface via jsx, qui sera compilée en fonction de rendu par des outils de compilation tels que babel ou tsc, puis exécutée pour générer vdom :
La fonction de rendu ici était React.createElement avant React17 :
Après React 17, il a été remplacé par jsx :
Ce runtime jsx sera automatiquement introduit et il n'est pas nécessaire de conserver une importation React pour chaque composant comme auparavant.
L'exécution de la fonction de rendu génère vdom :
La structure de vdom est la suivante :
Avant React16, ce vdom était rendu de manière récursive, en ajoutant, supprimant et modifiant le vrai dom.
Après que React16 ait introduit l'architecture fibre, il y a eu une étape supplémentaire : d'abord convertir vdom en fibre, puis restituer la fibre.
Le processus de conversion de vdom en fibre est appelé réconciliation, et le processus final d'ajout, de suppression et de modification du dom réel est appelé commit.
Pourquoi devons-nous procéder à une telle conversion ?
Étant donné que vdom n'a que des références aux enfants du nœud enfant, et aucune référence au nœud parent parent et aux autres nœuds frères, cela entraîne la nécessité de restituer de manière récursive tous les nœuds vdom vers le dom en même temps sans interruption.
Que se passe-t-il s'il est interrompu ? Étant donné que le nœud parent et les nœuds frères ne sont pas enregistrés, nous pouvons uniquement continuer à traiter les nœuds enfants, mais nous ne pouvons pas traiter les autres parties du vdom.
C'est pourquoi React a introduit ce type de structure fibreuse, qui a des références telles que le retour du nœud parent, le nœud enfant enfant, le nœud frère frère, etc., qui peuvent être interrompues, car tous les nœuds non traités peuvent être trouvés après interruption et récupération.
La structure du nœud de fibre est la suivante :
Ce processus peut être interrompu et, bien entendu, il peut être planifié, ce qui est un processus planifié.
Par conséquent, l'architecture fibre est divisée en trois étapes : planification, réconciliation (conversion de vdom en fibre) et validation (mise à jour vers dom).
Les hooks peuvent être utilisés dans les composants fonctionnels pour accéder à certaines valeurs, et ces valeurs sont stockées sur le nœud de fibre.
Par exemple, 6 hooks sont utilisés dans ce composant fonctionnel :
Ensuite, il y a une liste chaînée memorizedState de 6 éléments sur le nœud fibre correspondant :
Concaténé par suivant :
Différents hooks accèdent aux valeurs sur différents éléments de la liste chaînée memorizedState. C'est le principe des hooks de réaction.
Cette liste chaînée comporte une phase de création et une phase de mise à jour, vous constaterez donc que l'implémentation finale de useXxx est divisée en mountXxx et updateXxx :
La phase de montage consiste ici à créer des nœuds hook et à les assembler dans une liste chaînée :
La liste liée de crochets créée sera liée à l'attribut memorizedState du nœud de fibre.
Lors de la mise à jour, vous pouvez naturellement récupérer cette liste de hooks depuis le nœud fibre :
De cette façon, dans plusieurs rendus, l'API useXxx peut trouver l'état mémorisé correspondant sur le nœud fibre.
C'est le principe des hooks de réaction. Vous pouvez voir qu'il stocke le hook sur le nœud de la fibre.
Alors quelle est la différence avec préact ?
Preact est un framework plus léger compatible avec le code React. Il prend en charge les composants de classe et les composants de fonction, ainsi que les fonctionnalités de réaction telles que les hooks. Cependant, il n’implémente pas l’architecture fibre.
Parce qu'il considère principalement la taille finale (seulement 3 Ko), et non la performance ultime.
Nous venons d'apprendre que React stocke la liste de hooks sur le nœud fibre. Si preact n'a pas de nœud fibre, où la liste de hooks sera-t-elle stockée ?
En fait, il est facile de penser que la fibre modifie uniquement vdom pour améliorer les performances, et il n'y a pas de différence essentielle avec vdom. Alors pouvons-nous simplement stocker le hook sur vdom ?
En effet, preact place la liste de hooks sur vdom.
Par exemple, ce composant fonctionnel possède 4 hooks :
Son implémentation consiste à accéder au hook correspondant sur vdom :
Il ne divise pas le hook en deux étapes, le montage et la mise à jour, comme réagir, mais les fusionne pour le traitement.
Comme le montre la figure, il stocke les hooks dans le tableau composant.__hooks et y accède via des indices.
Ce composant est un attribut sur vdom :
Autrement dit, la valeur des hooks est stockée dans le tableau de vnode._component._hooks.
Comparez les différences entre React et Preact dans l'implémentation des hooks :
dans React, la liste de hooks est stockée sur l'attribut fiberNode.memorizedState, dans Preact, la liste de hooks est stockée sur l'attribut vnode._component._hooks.
La liste de hooks dans React est concaténée
À next, Et dans preact La liste des liens hook est un tableau.
React sépare la création et la mise à jour de la liste des liens hook
, l'implémentation des hooks ne repose pas sur la fibre, il suffit de trouver un endroit pour stocker les données du hook correspondant au composant. Tant qu'elles peuvent être récupérées pendant le rendu, peu importe où elles sont stockées.
Étant donné que le rendu vdom, fibre et composant est fortement lié, ils sont stockés dans ces structures.
Par exemple, lorsquereact ssr implémente des hooks, cela n'existe ni sur fibre ni sur vdom :
En fait, en plus de csr, le packagereact-dom peut également faire ssr :
Utilisez la méthode render dereact- dom quand rse :
Lorsque ssr, utilisez la méthode renderToString ou la méthode renderToStream de react-dom/server :
Pensez-vous que la conversion vdom vers fibre sera effectuée pendant le ssr ?
Certainement pas. Fiber est une structure introduite pour améliorer les performances de rendu lors de l'exécution dans le navigateur, rendre les calculs interrompus et effectuer des calculs en cas d'inactivité.
Le rendu côté serveur ne nécessite naturellement pas de fibre.
Si la fibre n’est pas nécessaire, où stocke-t-elle la liste des crochets ? vdom ?
Il peut effectivement être placé dans vdom, mais ce n'est pas le cas.
Par exemple, utilisez les hooksRef :
Il s'agit d'une liste chaînée concaténée avec next à partir de firstWorkInProgressHook.
Et firstWorkInProgressHook est le premier nœud hook créé avec createHook :
Il n'est pas monté sur vdom.
Pourquoi?
Étant donné que ssr ne doit être rendu qu'une seule fois et n'a pas besoin d'être mis à jour, il n'est pas nécessaire de le suspendre sur vdom.
Effacez simplement la liste des hooks chaque fois que vous terminez le traitement des hooks de chaque composant :
Par conséquent, lors de l'utilisation de React Ssr, des hooks existent dans les variables globales.
Comparez la différence dans les principes d'implémentation des hooks dans React Csr et ssr :
dans Csr, la fibre sera créée à partir de vdom, qui est utilisée pour rendre le rendu interrompu et améliorer les performances grâce à la planification inactive, mais dans ssr, elle ne sera pas rendue directement par vdom. Lors de l'utilisation
de csr, les hooks sont enregistrés sur le nœud de fibre, tandis que lors de l'utilisation de ssr, ils sont directement placés sur les variables globales et sont effacés après le traitement de chaque composant. Parce que CSR ne sera pas utilisé une seconde fois
, la création et la mise à jour des hooks seront divisées en deux phases : le montage et la mise à jour, tandis que SSR ne sera traité qu'une seule fois, et seule la phase de création.
Le principe de mise en œuvre des hooks n'est en réalité pas compliqué. , c'est-à-dire que dans un certain contexte, stockez une liste chaînée dans la liste chaînée, puis l'API hooks accède aux données correspondantes de différents éléments de la liste chaînée pour compléter leur logique respective. Ce contexte peut être vdom, fibre ou même une variable globale.
Cependant, l'idée des hooks est toujours très populaire. Le framework côté serveur Midway produit par Taobao a introduit l'idée des hooks :
Midway est un framework Node.js :
Le framework côté serveur n'a naturellement pas de structures telles que vdom et fibre, mais l'idée des hooks ne repose pas sur celles-ci. Pour implémenter l'API hooks, il vous suffit de placer une liste chaînée dans un certain contexte.
Midway implémente une API similaire aux hooks de réaction :
Je n'ai pas regardé spécifiquement où se trouve la liste de hooks, mais nous maîtrisons déjà le principe d'implémentation des hooks. Tant qu'il existe un contexte pour stocker la liste de hooks, elle peut être n'importe où.
les hooks de réaction sont une fonctionnalité qui a émergé après l'architecture de fibre de réaction. De nombreuses personnes croient à tort que les crochets doivent être implémentés avec de la fibre, respectivement, et avons constaté que. ce n'est pas le cas :
elle est
effacée.tout ira bien. Alors, les hooks de réaction doivent-ils s'appuyer sur la fibre pour l'implémenter ?
Évidemment non, il peut être utilisé avec fibre, vdom, variables globales ou même n'importe quel contexte.