Join the discussion
Comments
Loading comments...
Cookie preferences
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Join the discussion
Loading comments...
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Comment React met en cache les valeurs calculées et les références de fonctions.
La mémoïsation est une technique de mise en cache où React stocke le résultat d'un calcul coûteux et retourne le résultat mis en cache lors des rendus suivants — ignorant entièrement le calcul lorsque les entrées n'ont pas changé. useMemo met en cache les valeurs calculées. useCallback met en cache les références de fonctions. Les deux utilisent un tableau de dépendances pour décider quand recalculer.
useMemo(() => calculCoûteux(a, b), [a, b]) appelle la fonction au premier rendu et stocke le résultat. Lors des re-rendus, React vérifie si a ou b a changé. Si non, il retourne le résultat mis en cache sans rappeler la fonction.
useCallback(fn, [deps]) est équivalent à useMemo(() => fn, [deps]). Au lieu de mettre en cache la valeur de retour, il met en cache l'objet fonction. C'est important car JavaScript crée un nouvel objet fonction à chaque rendu — ce qui casse l'égalité référentielle pour les props de composants enfants.
React compare chaque valeur de dep avec Object.is() (égalité stricte). Les valeurs primitives (nombres, chaînes, booléens) sont comparées par valeur. Les objets et tableaux sont comparés par référence — donc un nouvel objet littéral '{''}' dans les deps déclenche toujours un recalcul.
Si toutes les deps sont égales à celles du rendu précédent, React retourne immédiatement la valeur mémoïsée sans appeler la fonction factory. Le composant se re-rend quand même — mais le calcul coûteux est ignoré.
Si une dep a changé, React rappelle la fonction factory, stocke le nouveau résultat et le retourne. L'ancienne valeur mise en cache est abandonnée.
Met en cache la valeur de retour d'un calcul. Recalcule uniquement lorsque les deps changent. Utile pour les calculs coûteux dérivés des props/state.
Met en cache une référence de fonction. Équivalent à useMemo(() => fn, deps). Essentiel lorsqu'on passe des callbacks à des composants enfants mémoïsés.
Deux objets/tableaux sont égaux seulement s'ils pointent vers la même adresse mémoire. '{''}' === '{''}' est faux. useMemo/useCallback préservent l'identité entre les rendus.
Le deuxième argument de useMemo/useCallback. React compare ces valeurs entre les rendus pour décider s'il faut recalculer.
Composant d'ordre supérieur qui mémoïse la sortie de rendu d'un composant. Fonctionne mieux combiné avec useCallback pour stabiliser les props callback.
1function ParentComponent({ items }) {2 const [filter, setFilter] = useState('');3 const [count, setCount] = useState(0);45 // useMemo: expensive filter only recomputes when items/filter change6 const filteredItems = useMemo(7 () => items.filter(item => item.name.includes(filter)),8 [items, filter]9 );1011 // useCallback: stable reference, doesn't cause Child re-render12 // when only 'count' changes13 const handleSelect = useCallback((id) => {14 console.log('Selected:', id);15 }, []); // no deps — function never needs to change1617 return (18 <>19 <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>20 <MemoizedChild items={filteredItems} onSelect={handleSelect} />21 </>22 );23}2425const MemoizedChild = React.memo(({ items, onSelect }) => {26 // Only re-renders when items or onSelect reference changes27 return items.map(i => <Item key={i.id} item={i} onSelect={onSelect} />);28});
Sans mémoïsation, chaque re-rendu parent crée de nouvelles références d'objets/fonctions, causant des re-rendus inutiles des enfants enveloppés par React.memo. useMemo et useCallback préservent la stabilité référentielle, rendant React.memo efficace et évitant les re-rendus en cascade dans les grands arbres de composants.
Your analytics dashboard processes 10,000 rows of sales data to calculate aggregates (sum, average, percentiles) and format display values. A clock that updates every second causes the entire dashboard to re-render — and the 50ms data processing runs every second.
The data transformation runs inside the render function without memoization. Every re-render (even from the clock ticker) recomputes all 10,000 rows. The dashboard becomes sluggish because 50ms of computation blocks the main thread on every tick.
Wrap the data transformation in `useMemo(() => processData(salesData), [salesData])`. Now the heavy computation only re-runs when `salesData` actually changes. Clock ticks cause re-renders but skip the 50ms computation entirely — React reuses the cached result.
Takeaway: useMemo is designed for expensive computations, not every value. The general guideline: if a computation takes more than 1ms or processes more than 100 items, it's a candidate for useMemo. Profile before optimizing — don't guess.
You wrap a heavy `DataTable` component in React.memo, but React DevTools still shows it re-renders every time the parent's unrelated state changes. Memo appears to 'not work.'
The parent passes `onRowClick={(id) => handleClick(id)}` — an inline arrow function. Every parent render creates a NEW function reference. React.memo compares props by reference: `oldFn !== newFn`, so it always re-renders. Memo is working correctly — the props ARE different every time.
Wrap the handler in `useCallback`: `const onRowClick = useCallback((id) => handleClick(id), [handleClick])`. Now the function reference is stable across renders. React.memo's shallow comparison sees identical props and correctly skips re-rendering the DataTable.
Takeaway: React.memo and useCallback/useMemo are a PAIR — they must be used together. React.memo is useless if any prop is an unstable reference (inline function, inline object, inline array). Always stabilize props with useCallback/useMemo before wrapping a child in React.memo.