Skip to content

The React Compiler

Historically, keeping React fast meant sprinkling memoization by hand: useMemo to cache expensive values, useCallback to keep function identities stable, React.memo to skip re-rendering a component whose props didn’t change. It works, but it’s noisy, easy to get wrong (a missing dependency, a wrong comparison), and clutters otherwise simple code.

The React Compiler is a build-time tool that does this automatically. It analyzes your components and inserts the equivalent memoization for you, so you write plain, direct code and still get the skip-unnecessary-work behavior:

// You write this — no useMemo, no useCallback, no memo:
function ProductList({ products, query }) {
const filtered = products.filter((p) => p.name.includes(query));
return (
<ul>
{filtered.map((p) => <Product key={p.id} product={p} onSelect={() => select(p.id)} />)}
</ul>
);
}
// The compiler memoizes `filtered`, the `onSelect` callbacks, and the elements
// so unrelated state changes don't re-run or re-render this needlessly.

Per the React docs, the compiler automatically applies the equivalent of memo to components, which is why it “reduces the need for manual memoization.”

What this means for the memoization advice

Section titled “What this means for the memoization advice”

The Hooks module covers useMemo/useCallback/memo in depth — and you still need to understand them, because you’ll read older code full of them and you need to know what they do. But going forward, the guidance flips:

  • With the compiler adopted: write straightforward code; don’t reach for useMemo/useCallback by default. Let the compiler decide.
  • Without it (or in libraries that ship un-compiled): manual memoization is still the tool.

So the skill shifts from “where do I add useMemo?” to “is my code written the way the compiler expects?”

The compiler can only safely memoize code that follows the Rules of React — chiefly that render is pure and you don’t mutate props, state, or values you don’t own. If you break those rules (mutate during render, read/write external things in the render body), the compiler can’t guarantee your component is safe to memoize, and may skip it. This is the practical payoff of the purity you learned in Foundations: it’s not just correctness hygiene, it’s what unlocks automatic optimization.

flowchart TB
  before["Before: you add
useMemo / useCallback / memo
by hand (noisy, error-prone)"] --> after["React Compiler
(build time)"]
  after --> result["Plain code +
auto-inserted memoization"]
  rules["Rules of React
(pure render, no mutation)"] --> after
Manual vs compiler memoization

Status, honestly: the React Compiler is the current, official auto-memoization tool, adopted via build configuration and function-level directives, and rolling out across the ecosystem. Treat it as the direction of travel — write compiler-friendly (pure) code now, and lean on it rather than hand-memoizing everything.

What does the React Compiler do?
With the compiler adopted, what is the guidance on manual memoization?
What must your code follow for the compiler to safely memoize it?