Comprendre le hook useMemo en React

Où comment traiter les valeurs dérivées en React, et optimiser le rendu de vos composants avec un hook dédié !

Article publié le 02/12/2024, dernière mise à jour le 02/12/2024

En programmation, et notamment dans le monde du front-end, il existe un concept important : celui des valeurs dérivées.

On parle aussi de valeurs calculées (ou “computed values” en anglais)

Une valeur dérivée est simplement une nouvelle donnée, créée à partir d’une ou plusieurs autres données existantes.

Voici un exemple simple :

function getPercentage(value, max){
	return Math.round((value / max) * 100) + "%";
}

Ici, à partir de deux valeurs, nous allons créer une troisième valeur dérivée, qui sera le pourcentage sous la forme d’une chaîne de caractère.

Mais alors quel est le problème ?

Les recalculs inutiles avec React

Maintenant ajoutons notre fonction pour calculer une valeur dérivée (pourcentage) dans un composant React très basique :

function MyComponent({ score, time }) {

	// Value is between 0 and 10
  function getPercentage(value){
		return Math.round((value / 10) * 100) + "%";
	}

  return (
	  <div>
		  <p>Time: {time}</p>
		  <p>Pourcentage: {getPercentage(score)}<p>
		</div>
	);
}

Et imaginons que la propriété time soit mise à jour toutes les 100ms.

La manière dont fonctionne le rendu de React fait que notre composant sera mis à jour toutes les 100ms, et donc notre fonction getPercentage sera également exécutée toutes les 100ms, même si les paramètres value et max de cette dernière n’ont pas changé de valeur.

Par conséquent le résultat de cette valeur dérivée n’a pas changé non plus, c’est donc un recalcul inutile, qui fait baisser les performances de notre rendu.

Et si il était possible de ne recalculer notre valeur dérivée que lorsque les valeurs utilisées dans le calculs changent ?

nicolasbrondinbernard_An_IBM_floppy_disk._100_white_background._d0e76172-f58e-454a-889c-8c5ed39506bb.png

Utiliser le hook useMemo

useMemo est un hook React puissant, conçu pour optimiser les performances en mémorisant le résultat d’une fonction tant que ses dépendances ne changent pas.

Lors du re-rendu d’un composant, React vérifiera les dépendances spécifiées et ne recalculera la valeur que si l’une d’entre elles a changé.

Voici un exemple de base, en reprenant notre fonction précédente :

import { useMemo } from 'react';

function MyComponent({ score, time }) {

  const percentage = useMemo(() => {
	  return Math.round((score / 10) * 100) + "%";
  }, [score]);

  return (
	  <div>
		  <p>Time: {time}</p>
		  <p>Pourcentage: {percentage}<p>
		</div>
	);
}

Ici, le pourcentage ne sera recalculée que si score change.

Même si le composant est re-rendu toutes les 100ms, notre valeur dérivée percentage ne sera pas recalculée inutilement.

Quand utiliser useMemo ?

  1. Pour éviter des calculs inutiles : Si une fonction de calcul est complexe ou dépend d’une grande quantité de données, useMemo peut réduire son impact sur les performances.
  2. Dans des composants à re-rendus fréquents : Si un composant re-render souvent à cause d’autres props ou états, useMemo peut empêcher des recalculs superflus.
  3. Pour optimiser des opérations coûteuses : Par exemple, le filtrage ou le tri de longues listes, ou encore des calculs mathématiques intensifs.

Exemple avec une opération coûteuse :

function FilteredList({ items }) {
  const sortedItems = useMemo(() => {
    return items.sort((a, b) => a.score - b.score;
  }, [items]);

  return <ul>{sortedItems .map(item => <li key={item}>{item}</li>)}</ul>;
}

Quand éviter useMemo ?

Il est important de ne pas abuser de useMemo.

Si l’opération à optimiser est légère ou si le composant ne se re-render pas fréquemment, useMemo pourrait ajouter une complexité inutile.

Ce hook a lui-même un coût en termes de gestion mémoire et de vérification des dépendances.

Mais si ce composant dépend d’autres props ou états qui provoquent des re-rendus fréquents, utiliser useMemo peut prévenir des recalculs inutiles, comme dans notre exemple.

Conclusion

useMemo est un outil essentiel pour optimiser les performances en React lors de l’utilisation de valeurs dérivées.

Et c’est aussi un très bon moyen de garder le code de votre template le plus propre possible !

Néanmoins pour des calculs simples ou des composants peu sollicités, il n’est pas toujours nécessaire de l’utiliser.


Vous avez terminé l'article ?

Commentaires (1)

pour laisser un commentaire

Benoit

12/05/2024, 9:37 PM

Très bien expliqué !

NicolasBrondinBernard

12/06/2024, 9:30 AM

@Benoit Merci 🙏