React7h estimated

Rendering Performance & Memoization

Difficulty
Importance

The problem

As a component tree grows, re-rendering components whose output hasn't actually changed wastes work — memoization skips that wasted work by reusing a previous result when the inputs are provably the same, but applying it incorrectly can silently break correctness or provide no benefit at all.

Why now

The virtual DOM and reconciliation already established that re-rendering (the function running again) is distinct from and cheaper than a real DOM update, but it's still not free at scale. Memoization is a direct, practical application of the pure-function idea from higher-order-functions: if a function's output depends only on its inputs, and the inputs haven't changed, you can safely skip calling it again.

Mental model

Memoization is a cache with exactly one entry: remember the last inputs and output, and if the new inputs are equal to the last ones, return the cached output instead of recomputing. This only works safely if the wrapped function is pure (same input always gives same output) — which is exactly why memoizing a component with side effects or unstable references (a new object literal every render) either fails silently or does nothing.

Requires

Used in

Projects

  • Use the Profiler to identify a component that re-renders unnecessarily on every parent update, then wrap it in React.memo and confirm the re-render disappears
  • Break memoization by passing an inline object or function as a prop, observe that React.memo provides no benefit, then fix it with useMemo/useCallback

Examples

  • React.memo(ExpensiveList) skips re-rendering ExpensiveList entirely if its props are shallow-equal to the previous render's
  • Passing onClick={() => doThing()} inline creates a new function reference every render, defeating a child's React.memo unless wrapped in useCallback

Resources

Mastery checklist