Memoization (useMemo, React.memo)
Avoid redundant work and unnecessary re-renders: useMemo for expensive or referentially-sensitive values, useCallback for stable callbacks, React.memo for components that should skip re-render when props are equal.
The problem I keep seeing
When a parent re-renders, it recreates objects and arrays and runs expensive derivations. Children receive new references and re-render even when the logical data didn’t change. You want to stabilize values (so dependency arrays and child props don’t churn) and skip re-rendering heavy children when their props are unchanged.
Naive approach
Compute derived data and create objects inline every render. Pass them as props; the child re-renders every time because references change. No memoization.
First improvement
Wrap expensive or referentially-sensitive values in useMemo with correct dependencies so they only change when deps change. Wrap presentational components in React.memo so they re-render only when props are not equal (shallow compare).
Remaining issues
- When to memo: Not everywhere—memo has a cost (prop comparison). Use when the parent re-renders often and the child is expensive, or when you need a stable reference for
useEffect/useMemodeps. - useCallback: For callbacks passed to memoized children, use
useCallbackso the function reference is stable; otherwise the child sees a new prop every time. - Dependency array: Wrong deps can cause stale values or unnecessary recomputation; keep deps accurate.
Production pattern
Use useMemo for: expensive derivations, or objects/arrays passed to memoized children (so the reference is stable). Use useCallback for handlers passed to memoized children or listed in effect deps. Use React.memo on leaf or list-item components that are expensive and receive stable props. Don’t memo by default—profile first; add memoization where you measure a real win.
When I use this
- useMemo: Heavy computation (filter/sort of large list, complex derived state), or when you need a stable object/array for a dependency array or for a child that is memoized.
- useCallback: Event handlers or callbacks passed to memoized children, or used in
useEffect/useMemodeps. - React.memo: List rows, heavy presentational components, when the parent re-renders often and props are often unchanged.
React Compiler
useMemo / useCallback / memo. Until then, apply these patterns where profiling shows benefit.Gotchas
- Shallow compare:
React.memodoes shallow comparison; if you pass an object or array created inline, the reference changes every time and memo doesn’t help. Stabilize withuseMemooruseCallback. - Over-memoizing: Wrapping every component and every value adds comparison cost and complexity. Use for hot paths and expensive subtrees.