Under The Hood
frontend react React Compiler (React 19)

React Compiler: automatic memoization

Last updated
Prerequisites:
React rendering model
useMemo/useCallback and memo() basics
  • react
  • compiler
  • memoization
  • performance
  • babel
  • react-compiler

Read at your depth

The practical view

Until now you manually wrapped values in useMemo and functions in useCallback, and wrapped components in memo() to skip re-renders. The React Compiler (installed as a Babel/SWC plugin, e.g. babel-plugin-react-compiler) analyzes your components and automatically applies memoization wherever it is safe: it memoizes computed values, callback functions, and JSX subtrees, so hand-written useMemo/useCallback/memo become mostly unnecessary. You keep coding normally — no new syntax — and the compiler inserts the caching. Rules of React still apply: no mutating props/state during render, hooks called unconditionally.

The same idea in other frameworks

react equivalent
// Compiler handles this:
const doubled = compute(items); // memoized automatically
const onSave = () => save(draft); // memoized automatically

Legacy vs modern

Manual useMemo/memo scaffolding vs compiler-auto memoization

Hand-written memoization is error-prone and verbose; the compiler derives the same caching automatically and stays correct as the component evolves.

before → after
Manual memoization
const list = useMemo(() => items.filter(byQuery), [items, query]);
const onPick = useCallback((id) => pick(id), []);
const Row = memo(TableRow);
Compiler memoization
const list = items.filter(byQuery);
const onPick = (id) => setSelected(id);

Interview gotchas

Context

The interviewer wants to distinguish a mechanical understanding ('it does what I do by hand') from understanding the analysis the compiler performs.

The mechanical answer

The compiler does not blindly cache — it performs a reactive-value analysis: for each expression it determines which inputs are reactive (derived from props/state/hooks) and caches only when the computation is pure with respect to those inputs and the inputs can be compared with Object.is. It can also split JSX into memoized subcomponents and reorder computations. Hand-written useMemo caches based on the dependency array you guessed; the compiler's cache is derived from actual data flow, so it stays correct when the component changes — manual memoization goes stale the moment someone edits a dep array incorrectly, while the compiler's output is regenerated from source every build.

Trap

The trap is claiming the compiler removes the need for understanding rendering, or that it makes components 'not re-render'. Re-renders still happen for the parent; the compiler prunes the child work when inputs are unchanged. Another trap: 'it replaces React's reconciliation' — it does not; it optimizes at the component-function level on top of the existing commit pipeline.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.