29
votes

Utilisation de useMemo au lieu de problème de syntaxe React.memo

J'ai besoin de faire une démonstration de l'utilisation de React Hooks useMemo. J'ai un code de travail qui est le suivant et qui fait ce que je veux:

const SpeakerDetail = React.useMemo(() => {
   ({ id,

J'ai trouvé un lien qui montre que je pourrais utiliser une syntaxe plus comme celle-ci, mais je ne peux pas le comprendre exactement.

C'est ce que j'ai obtenu:

const SpeakerCardDetail = React.memo(
  ({id,...

Mais clairement non. Je comprends que React.memo résout le problème, mais je dois montrer useMemo en action et j'espère qu'il existe une syntaxe alternative que je peux utiliser.


3 commentaires

attendez ce que vous devez faire? n'importe quel exemple d'utilisation de useMemo ?


React.memo permet aux composants fonctionnels d'avoir la même optimisation que PureComponent fournit pour les composants basés sur les classes. useMemo est pour mémoriser les appels de fonction à l'intérieur du composant fonctionnel. Il serait difficile de les remplacer par un autre car ils ont des objectifs différents.


J'espère pouvoir obtenir le même résultat que React.memo, c'est-à-dire que le retour de la fonction pure est sauvegardé avec la mémorisation.


3 Réponses :


45
votes

React.memo et React.useMemo ne sont pas du tout équivalents (ne vous fiez pas à la similitude de dénomination). Voici une citation de React.memo doc :

React.memo est un composant d'ordre supérieur .

C'est donc un HOC qui peut optimiser le rendu de votre composant étant donné qu'il rend la même sortie avec les mêmes propriétés.

React.useMemo en revanche est plus générique et renvoie une valeur mémorisée :

Passez une fonction «créer» et un tableau de dépendances. useMemo ne recalculera la valeur mémorisée que lorsque l'une des dépendances ( a ou b ) a changé.

const memoizedValue = useMemo(
  () => computeExpensiveValue(a, b), 
  [a, b]
);

Et bien qu'il puisse être piraté pour être utilisé à la place de React.memo , ce n'est pas son but et cela ajoutera à la confusion plus qu'il n'aidera. useMemo est un hook et est soumis à certaines règles d'utilisation .

Et il y a aussi cet avertissement:

À l'avenir, React peut choisir d '«oublier» certaines valeurs précédemment mémorisées et de les recalculer lors du prochain rendu, par exemple pour libérer de la mémoire pour les composants hors écran. Écrivez votre code pour qu'il fonctionne toujours sans useMemo - puis ajoutez-le pour optimiser les performances.


3 commentaires

Merci. Je suis arrivé à la même conclusion et j'ai été trompé par la dénomination. J'utilise maintenant comme exemple les résultats d'une sorte avant le rendu.


Cependant, je dois dire que j'ai regardé cet exemple pendant un long moment parce qu'il leur fait ressentir un peu la même chose. codesandbox.io/s/7m03xn9wlx


Je ne suis pas d'accord avec "cela ajoutera à la confusion". Une fois que vous utilisez des crochets partout, pourquoi retourneriez-vous à HOC pour réaliser la même chose? :)



21
votes

Alors que memo est un HOC et useMemo est un hook, vous pouvez les utiliser pour obtenir le même résultat.

Pour le contexte, HOC est un modèle React plus ancien qui a été utilisé pendant de nombreuses années avec des composants basés sur les classes et fonctionnels. Vous pouvez toujours l'utiliser aujourd'hui (il n'y a pas de plan de dépréciation).

Les hooks sont un concept relativement nouveau (environ un an) qui améliore les composants fonctionnels et, dans de nombreux cas, simplifie considérablement le code . C'est pourquoi de nombreux développeurs s'orientent vers l'utilisation de hooks.

Quoi qu'il en soit, memo et useMemo prennent deux arguments: une fonction et des accessoires. Si aucun des accessoires ne change lors des relances suivantes, la fonction n'est pas exécutée à nouveau et renvoie à la place le résultat précédent. Ceci, en effet, remplace les callbacks shouldComponentUpdate , par une approche purement fonctionnelle.

Avec memo , votre code ressemblerait à ceci:

function SpeakerCardDetail(props) {
  return useMemo(
    () => <div>{props.name}</div>
  ,
    [props.name]
  )
}

Avec useMemo , vous useMemo :

const SpeakerCardDetail = React.memo(
  (props) => <div>{props.name}</div>
,
  // return true if passing nextProps to render would return the same result as passing prevProps to render, otherwise return false
  (prevProps, nextProps) => prevProps.name === nextProps.name
)

Notez que useMemo est utilisé à l'intérieur de la fonction de votre composant, tandis que le memo enveloppe la fonction.

Plus traditionnellement, useMemo pourrait être écrit comme useMemo :

function SpeakerCardDetail(props) {
  return useMemo(
    () => <div>{props.name}</div>
  )
}

Désormais, le code ci-dessus serait à nouveau rendu à chaque fois, rendant la fonction useMemo un peu inutile. Pour faire fonctionner sa magie, nous devons ajouter le deuxième argument. (le memo fonctionne toujours même sans spécifier le deuxième argument mais vous pouvez l'ajouter pour le personnaliser)

Il y a une légère différence dans le format du deuxième argument. memo attend une fonction qui compare les accessoires précédents et actuels, tout comme shouldComponentUpdate fait pour les composants de classe.

const SpeakerCardDetail = (props) => useMemo(() => <div>{props.name}</div>)

useMemo , en revanche, attend un tableau comme deuxième argument. Chaque fois que les valeurs du tableau changent, la fonction est à nouveau exécutée.

const SpeakerCardDetail = React.memo(
  (props) => <div>{props.name}</div>
)

Il n'y a vraiment pas plus de magie que ça. Les deux memo et useMemo sont utilisés pour memoize le résultat d'une fonction, la seule différence est memo est un HOC (et peut être utilisé pour envelopper à la fois classe et composants fonctionnels) qui useMemo est un crochet (et ne peut être utilisé à l' intérieur des composants fonctionnels) .


4 commentaires

Pouvez-vous nous suggérer quelle est la meilleure façon d'utiliser les deux approches?


@Muhammad Ni l'un ni l'autre n'est strictement meilleur que l'autre. Si vous utilisez des composants de classe, vous devez utiliser memo . Si vous utilisez des composants fonctionnels avec des hooks, vous voudrez peut-être utiliser useMemo (bien que, dans ce cas, vous puissiez également utiliser memo ). useMemo également un deuxième argument plus concis. En fin de compte, ce n'est qu'une question de préférence. Toute différence de performance doit être négligeable.


Lorsque le composant est à l'intérieur d'une condition, avec useMemo, vous obtenez moins de crochets que prévu, donc dans ce cas, je suppose que le mémo est la seule option.


En fin de compte, si vous êtes à l'aise avec l'utilisation des hooks et que vous les utilisez tout au long de votre projet, vous préférerez peut-être useMemo pour la "cohérence". Cependant, comme le note @GoranJakovljevic, les règles habituelles des hooks s'appliquent, vous pouvez donc toujours revenir à React.memo . Si vous n'utilisez pas de hooks, utilisez toujours React.memo .



0
votes

Je viens de rédiger un article sur les différences entre React.memo et useMemo que vous pouvez trouver ici


Pour résumer / tldr:

React.memo est un composant d'ordre supérieur (HOC pour faire court) qui mémorisera un composant de réaction basé sur les accessoires.

export function SomeComponent({ num }) {
  const res = useMemo(() => num * 10, [num])
  return <p>{res}</p>
}

useMemo est un hook de réaction qui mémorisera la valeur renvoyée par la fonction que vous lui fournissez.

export function SomeComponent({ num }) {
  return <p>{num * 10}</p>
}

export default React.memo(SomeComponent, function areEqual(
  prevProps,
  nextProps
) {
  if (prevProps.num !== nextProps.num) {
    return false
  }
  return true
})

Source: https://atomizedobjects.com/blog/react/react-memo-vs-use-memo/


0 commentaires