Skip to content

useMemo Hook

useMemo caches the result of an expensive calculation between renders, recomputing only when dependencies change. Use it after profiling — not by default on every value.

Caching Computed Values

const value = useMemo(() => compute(a, b), [a, b]) runs compute only when a or b change. Otherwise React returns the cached result from the previous render.

Memoization trades memory for CPU. Unnecessary useMemo adds complexity without measurable benefit. Profile first with React DevTools Profiler.

const sortedItems = useMemo(
  () => [...items].sort((a, b) => a.name.localeCompare(b.name)),
  [items]
);

Sorting a large array on every render is a classic useMemo candidate.

useMemo Syntax

const memoized = useMemo(() => {
  return expensiveComputation(a, b);
}, [a, b]);
  • First argument is a function returning the value to cache.
  • Second argument is the dependency array.
  • Returns cached value when deps unchanged.
  • Not a semantic guarantee in concurrent React — treat as optimization hint.

useMemo vs useCallback vs React.memo

Three related but distinct optimization tools.

API Caches
useMemo Computed value result
useCallback Function reference
React.memo Component render output
Dependency array Controls when cache invalidates
When to skip Cheap computations, premature optimization

When NOT to useMemo

Primitive calculations, simple string concatenation, and small array filters rarely benefit. Memoization has its own overhead — measuring is essential.

  • Don't memoize everything by default.
  • Derive simple values inline during render.
  • Fix slow renders by restructuring before memoizing.
  • Use Profiler to identify actual bottlenecks.

Referential Equality for Dependencies

Child components wrapped in React.memo re-render when props change by reference. useMemo for objects/arrays passed as props prevents false-positive re-renders.

const config = useMemo(() => ({ theme, locale }), [theme, locale]);
<Chart config={config} />

Common Mistakes

  • Memoizing cheap operations everywhere.
  • Missing dependencies causing stale memoized values.
  • Confusing useMemo with useEffect.
  • Expecting useMemo to prevent renders of the current component.

Key Takeaways

  • useMemo caches expensive computation results.
  • Recomputes when dependencies change.
  • Profile before optimizing.
  • Also useful for stable object/array references as props.

Pro Tip

If you're reaching for useMemo on every render, ask whether splitting the component or moving computation down the tree fixes the root cause.