Maison >interface Web >js tutoriel >Comment mettre en œuvre la mémorisation dans React pour améliorer les performances
Ce tutoriel expliquera comment implémenter la mémorisation dans React. La mémorisation améliore les performances en stockant les résultats des appels de fonction coûteux et en renvoyant ces résultats mis en cache en cas de besoin à nouveau.
Nous couvrirons les éléments suivants:
Cet article suppose que vous avez une compréhension de base des composants de classe et des composants fonctionnels dans React. Si vous souhaitez consulter ces sujets, consultez la documentation officielle React Composants and Props.
React.PureComponent
et React.memo()
peuvent être utilisés pour implémenter la mémoire dans les composants de classe et les composants fonctionnels, respectivement. Ces méthodes empêchent le réinstallation inutile si les accessoires ou l'état du composant n'ont pas changé. React.memo()
est utilisé. Pour éviter cela, vous pouvez utiliser le crochet useCallback()
pour empêcher la recréation de la fonction à chaque fois que le composant parent rend. Avant d'entrer dans l'introduction détaillée de la mémoire dans React, examinons d'abord comment React rend l'interface utilisateur à l'aide de Dom virtuel.
Le DOM ordinaire contient essentiellement un ensemble de nœuds représentés comme un arbre. Chaque nœud dans le DOM est une représentation de l'élément d'interface utilisateur. Chaque fois qu'un changement d'état se produit dans l'application, les nœuds correspondants de cet élément d'interface utilisateur et tous ses éléments enfants sont mis à jour dans le DOM, puis l'interface utilisateur est repeint pour refléter les modifications mises à jour.
En utilisant des algorithmes d'arbres efficaces, les mises à jour des nœuds sont plus rapides, mais le re-dessin est plus lent et lorsque le DOM a un grand nombre d'éléments d'interface utilisateur, il aura un impact sur les performances. Par conséquent, un Dom virtuel est introduit dans React.
Il s'agit d'une représentation virtuelle du vrai Dom. Maintenant, chaque fois que l'état de l'application change de toute façon, React ne met pas directement à jour le vrai DOM, mais crée un nouveau Dom virtuel. React compare ensuite ce nouveau Dom virtuel avec le Dom virtuel créé précédemment pour trouver les différences qui doivent être redéranées.
En utilisant ces différences, le DOM virtuel mettra à jour efficacement le DOM réel avec les modifications. Cela améliore les performances car le DOM virtuel ne met pas simplement à jour les éléments de l'interface utilisateur et tous ses éléments enfants, mais ne met efficacement que les changements minimaux nécessaires dans le DOM réel.
Dans la section précédente, nous avons vu comment React peut effectuer efficacement les mises à jour DOM à l'aide de Dom virtuel pour améliorer les performances. Dans cette section, nous examinerons un cas d'utilisation qui explique pourquoi la mémoire est nécessaire pour améliorer encore les performances.
Nous créerons une classe parent avec un bouton pour incrémenter la variable d'état nommée Count. Le composant parent appelle également le composant enfant et y transmet l'hélice. Nous avons également ajouté l'instruction Console.log () à la méthode de rendu de deux classes:
<code class="language-javascript">//Parent.js class Parent extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } handleClick = () => { this.setState((prevState) => { return { count: prevState.count + 1 }; }); }; render() { console.log("Parent render"); return ( <div classname="App"> <button onclick="{this.handleClick}">Increment</button> <h2>Count: {this.state.count}</h2> <child name='{"joe"}'></child> </div> ); } } export default Parent;</code>
Le code complet de cet exemple est disponible sur codes et boîte.
Nous allons créer une classe d'enfants qui prend l'hélice passée par le composant parent et l'afficher dans l'interface utilisateur:
<code class="language-javascript">//Child.js class Child extends React.Component { render() { console.log("Child render"); return ( <div> <h2>Name: {this.props.name}</h2> </div> ); } } export default Child;</code>
chaque fois que nous cliquons sur le bouton dans le composant parent, la valeur de nombre change. Puisqu'il s'agit d'un changement d'état, la méthode de rendu du composant parent est appelée.
Les accessoires transmis aux sous-classes restent inchangés chaque fois que le parent se redevienne, de sorte que les composants de l'enfant ne doivent pas être réindiés. Cependant, lorsque nous exécutons le code ci-dessus et continuons à incrémenter le nombre, nous obtenons la sortie suivante:
<code>Parent render Child render Parent render Child render Parent render Child render</code>
Vous pouvez incrémenter le nombre de l'exemple ci-dessus vous-même dans le bac à sable suivant et afficher la sortie de la console:
[Le lien codes et boîte doit être intégré ici, mais comme je ne peux pas accéder aux sites Web externes, il ne peut pas être fourni]
À partir de cette sortie, nous pouvons voir que lorsque le composant parent se redevienne, il redevient également le composant enfant - même si les accessoires transmis au composant enfant n'ont pas changé. Cela amènera le Dom virtuel du sous-composant à effectuer une vérification de différence avec le DOM virtuel précédent. Puisqu'il n'y a pas de différence dans le composant enfant - parce que les accessoires sont les mêmes dans tous les redevateurs - le vrai Dom n'est pas mis à jour.
Nous avons l'avantage de performance de ne pas mettre à jour le vrai Dom inutilement, mais nous pouvons voir ici qu'un nouveau Dom virtuel est créé et qu'une vérification de différence est effectuée même si les composants de l'enfant n'ont pas réellement changé. Pour les petits composants de réaction, cette performance est négligeable, mais pour les grands composants, l'impact des performances est excellente. Pour éviter cette réinstallation et la vérification virtuelle DOM, nous utilisons la mémoire.
Dans le contexte d'une application React, la mémorisation est une technique où chaque fois que le composant parent se redevienne, le composant enfant ne renvoie que lorsque les accessoires changent. Si les accessoires n'ont pas changé, il n'exécute pas la méthode de rendu, mais renvoie le résultat mis en cache. Étant donné que la méthode de rendu n'est pas exécutée, aucun DOM virtuel et des contrôles différentiels ne sont créés - améliorant ainsi les performances.
Voyons maintenant comment la mémorisation est implémentée dans les classes et les composants de réaction fonctionnels pour éviter cette réinstallation inutile.
(Le contenu suivant est similaire au texte d'origine, sauf que la langue et l'expression ont été un peu ajustées, et que l'emplacement et le format de l'image sont maintenus inchangés. Je ne peux pas fournir de lien de boîte et de boîte en raison de l'incapacité d'accéder aux sites Web externes .)
Pour implémenter la mémoire dans les composants de la classe, nous utiliserons React.PureComponent
. React.PureComponent
implémente shouldComponentUpdate()
, ce qui fait des comparaisons peu profondes entre l'état et les accessoires et rend les composants ne réagissent que si les accessoires ou les changements d'état.
Modifiez le composant enfant en code ci-dessous:
<code class="language-javascript">//Parent.js class Parent extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } handleClick = () => { this.setState((prevState) => { return { count: prevState.count + 1 }; }); }; render() { console.log("Parent render"); return ( <div classname="App"> <button onclick="{this.handleClick}">Increment</button> <h2>Count: {this.state.count}</h2> <child name='{"joe"}'></child> </div> ); } } export default Parent;</code>
Le code complet de cet exemple est le suivant: [Le lien de codes et la boîte doit être intégré ici]
Le composant parent reste inchangé. Maintenant, lorsque nous augmentons le nombre dans le composant parent, la sortie de la console est la suivante:
<code class="language-javascript">//Child.js class Child extends React.Component { render() { console.log("Child render"); return ( <div> <h2>Name: {this.props.name}</h2> </div> ); } } export default Child;</code>
Pour le premier rendu, il appelle la méthode de rendu des composants parents et enfants.
Dans chaque rendu incrémentiel incrémentiel, seule la fonction de rendu du composant parent est appelée. Les composants de l'enfant ne seront pas remis en fonction.
Pour implémenter la mémoire dans un composant REACT fonctionnel, nous utiliserons React.memo()
. React.memo()
est un composant d'ordre élevé (HOC) qui fait un travail similaire à PureComponent
pour éviter un rediffusion inutile.
Ce qui suit est le code des composants fonctionnels:
<code>Parent render Child render Parent render Child render Parent render Child render</code>
Nous convertissons également le composant parent en un composant fonctionnel comme indiqué ci-dessous:
<code class="language-javascript">//Child.js class Child extends React.PureComponent { // 将React.Component更改为React.PureComponent render() { console.log("Child render"); return ( <div> <h2>Name: {this.props.name}</h2> </div> ); } } export default Child;</code>
Le code complet de cet exemple peut être vu dans le bac à sable suivant: [le lien de codes et de boîte doit être intégré ici]
Maintenant, lorsque nous incrément le nombre dans le composant parent, la console sortira ce qui suit:
<code>Parent render Child render Parent render Parent render</code>
React.memo()
Problèmes avec la fonction Prop Dans l'exemple ci-dessus, nous constatons que lorsque nous utilisons React.memo()
hoc pour nos composants enfants, même si le composant parent est renvoyé, les composants de l'enfant ne sont pas rédigents.
Cependant, un petit problème à noter est que si nous passons la fonction comme un accessoire au composant enfant, le composant enfant sera renvoyé même si nous utilisons React.memo()
. Regardons un exemple.
Nous modifierons le composant parent comme indiqué ci-dessous. Ici, nous ajoutons une fonction de gestionnaire que nous passons à la composante enfant en tant qu'accessoires:
<code class="language-javascript">//Child.js export function Child(props) { console.log("Child render"); return ( <div> <h2>Name: {props.name}</h2> </div> ); } export default React.memo(Child); // 在此处为子组件添加HOC以进行记忆化</code>
Le code du sous-composant reste inchangé. Nous n'utilisons pas une fonction passées comme accessoires dans un composant enfant:
<code class="language-javascript">//Parent.js import React, { useState } from 'react'; import Child from './Child'; export default function Parent() { const [count, setCount] = useState(0); const handleClick = () => { setCount(count + 1); }; console.log("Parent render"); return ( <div> <button onclick="{handleClick}">Increment</button> <h2>Count: {count}</h2> <child name='{"joe"}'></child> </div> ); }</code>
Maintenant, lorsque nous augmentons le nombre dans le composant parent, il renforce et redevient le composant enfant même si les accessoires n'ont pas changé.
Alors, qu'est-ce qui a provoqué la refonte des composants de l'enfant? La réponse est que chaque fois que le composant parent se redevienne, une nouvelle fonction de gestionnaire est créée et transmise au composant enfant. Maintenant, puisque la fonction de gestionnaire est recréée chaque fois qu'elle est remensionnée, le composant enfant constatera que la référence du gestionnaire a été modifiée lorsqu'il s'agit d'une comparaison superficielle des accessoires et des remensions du composant enfant.
Dans la section suivante, nous verrons comment résoudre ce problème.
useCallback()
pour éviter davantage de relances Le principal problème qui entraîne la réadaptation du composant enfant est la recréation de la fonction du programme, qui modifie les références transmises à la composante enfant. Par conséquent, nous avons besoin d'un moyen d'éviter ces loisirs. Si le gestionnaire n'est pas recréé, la référence au gestionnaire ne changera pas - les composants de l'enfant ne seront donc pas remis en fonction.
Pour éviter de recréer la fonction à chaque fois que le composant parent rend, nous utiliserons un crochet React appelé useCallback()
. Des crochets ont été introduits dans React 16. Pour en savoir plus sur les crochets, vous pouvez consulter la documentation officielle de REACT ou consulter «React Hooks: Comment démarrer et construire le vôtre».
useCallback()
Le crochet accepte deux paramètres: la fonction de rappel et la liste de dépendances.
Considérez l'exemple useCallback()
suivant:
<code class="language-javascript">//Parent.js class Parent extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } handleClick = () => { this.setState((prevState) => { return { count: prevState.count + 1 }; }); }; render() { console.log("Parent render"); return ( <div classname="App"> <button onclick="{this.handleClick}">Increment</button> <h2>Count: {this.state.count}</h2> <child name='{"joe"}'></child> </div> ); } } export default Parent;</code>
Ici, useCallback()
est ajouté à la fonction handleClick()
. Le deuxième paramètre [x,y]
peut être un tableau vide, une dépendance ou une liste de dépendances. La fonction handleClick()
est recréée chaque fois que des dépendances mentionnées dans le deuxième changement de paramètre.
Si la dépendance mentionnée dans useCallback()
n'a pas changé, la version mémorisée de la fonction de rappel (comme le premier paramètre) est renvoyée. Nous allons changer notre composant fonctionnel parent pour utiliser le useCallback()
Hook pour les gestionnaires transmis au composant enfant:
(Ceci est similaire au texte d'origine, sauf que la langue et l'expression sont un peu ajustées, et la position et le format de l'image sont maintenus inchangés. Je ne peux pas fournir de lien de codes et de boîte en raison de l'incapacité d'accéder aux sites Web externes.)
La mémorisation est une bonne technique pour améliorer les performances de l'application REACT en évitant le réinstallation inutile des composants lorsque les accessoires ou l'état du composant n'ont pas changé. Vous pourriez penser à ajouter de la mémorisation à tous les composants, mais ce n'est pas un bon moyen de construire des composants React. Vous devez utiliser la mémoire uniquement si le composant remplit les conditions suivantes:
Dans ce tutoriel, nous avons vu:
React.memo()
pour les composants de réaction fonctionnels et React.PureComponent
comme composants de classe React.memo()
Un cas d'utilisation, même après avoir utilisé useCallback()
Comment utiliser J'espère que vous trouverez cette introduction pour réagir la mémoire utile!
(Ceci est similaire au texte d'origine, mais certains ajustements ont été apportés à la langue et à l'expression.)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!