React
medium
senior
Memoization pitfalls in React — when does memo / useMemo / useCallback hurt?
Memoization adds bookkeeping cost for every render. It only pays off when the work is expensive AND the deps are actually stable AND a downstream consumer cares about identity. Most of the time it makes code noisier without measurable wins.
6 min read·~12 min to think through
React.memo, useMemo, useCallback aren't free. Each adds:
- A dependency-array comparison every render.
- An extra allocation for the cache slot.
- Cognitive overhead for readers.
When memoization actually helps (all must be true):
- Expensive work — a real computation, not a string concat. Profile first.
- Stable deps — the inputs don't change every render. If they do, memo just adds bookkeeping for nothing.
- A consumer that cares about reference equality — e.g.,
React.memochild,useEffectdependency.
Common misuses:
- Wrapping every callback in useCallback — but the receiving component isn't memoized, so reference stability changes nothing.
- Memoizing primitives —
useMemo(() => count + 1, [count])saves nothing. - Memoizing inside a parent that re-renders constantly — deps change every time; memo never hits.
- Inline objects in deps —
useMemo(..., [{ a }])recreates the dep object every render; memo never hits.
When memoization can be net negative:
- Tight loops where the comparison cost > the saved work.
- High-churn render paths (e.g. animation frames) — allocations from cache slots add up.
React 19 + React Compiler auto-memoizes much of this; manual hooks become rarer. Until your codebase compiles, the heuristic is: profile, identify the wasted re-render, then surgically apply memoization to the smallest possible boundary.
Code
Follow-up questions
- •What does the React Compiler do, and how does it affect manual memoization?
- •When should you use React.memo vs useMemo vs useCallback?
- •How do you measure whether a memoization actually helped?
Common mistakes
- •Wrapping everything 'just in case'.
- •Memoizing with deps that change every render — pointless.
- •Treating memoization as a guarantee — React may evict.
Performance considerations
- •Profile in a production build with React DevTools Profiler. The dev build distorts measurements.
Edge cases
- •useMemo's cache can be discarded by React under memory pressure — it's best-effort.
- •Inline arrays/objects in deps mean the memo never hits.
Real-world examples
- •React 19 announcement explicitly addresses memoization fatigue — the compiler is meant to make manual memo unnecessary in most cases.
Senior engineer discussion
Senior signal: discuss profiling-driven optimization, React Compiler's auto-memoization model, and how identity-based memoization differs from structural memoization (immer, immutable.js).
Related questions
React
Easy
5 min