Sachez quand React.memo, useMemo et useCallback accélèrent vraiment votre application, et quand ils la compliquent pour rien.
Ouvrir cette leçon dans KodokonQuand un composant re-rend, tous ses enfants re-rendent par défaut, que leurs props aient changé ou non. Ce n'est pas un drame : un rendu ne touche au DOM que si la sortie change. La mémoïsation devient pertinente quand des rendus fréquents rencontrent des sous-arbres coûteux. Trois outils, trois cibles : React.memo saute le rendu d'un composant si ses props sont superficiellement égales, useMemo met en cache une valeur calculée, useCallback met en cache une fonction. Les trois reposent sur l'égalité de références.
import { memo } from "react";
const Row = memo(function Row({ item, onSelect }) {
return (
<li onClick={() => onSelect(item.id)}>{item.label}</li>
);
});La chaîne ne vaut que par son maillon le plus faible. Si une seule prop reçoit une référence neuve à chaque rendu - fonction fléchée inline, objet ou tableau littéral -, la comparaison de memo échoue et le composant re-rend quand même. useCallback stabilise la référence de la fonction pour que la comparaison réussisse.
import { useCallback } from "react";
function List({ items }) {
const handleSelect = useCallback((id) => {
console.log("selected:", id);
}, []);
return (
<ul>
{items.map((item) => (
<Row
key={item.id}
item={item}
onSelect={handleSelect}
/>
))}
</ul>
);
}useMemo a deux usages légitimes : éviter un calcul réellement coûteux (tri ou agrégation sur des milliers d'éléments), et stabiliser une référence consommée par un enfant mémoïsé ou listée dans les dépendances d'un effet. Pour un calcul trivial, le cache coûte plus cher qu'il ne rapporte : comparaison des dépendances, mémoire retenue, lecture alourdie.
import { useMemo } from "react";
function Stats({ orders }) {
const total = useMemo(() => {
return orders.reduce(
(sum, order) => sum + order.amount,
0
);
}, [orders]);
return <p>Total : {total} €</p>;
}