C.W.K.
Stream
Lesson 04 of 06 · published

The React Compiler — Automatic Memoization

~13 min · react-compiler, memoization, build

Level 0React Novice
0 XP0/54 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
For ten years, React devs sprinkled useMemo and useCallback to avoid re-renders. The React Compiler reads your code at build time and inserts those memoizations automatically. The whole 'wrap everything just in case' era is ending.

What it does

The React Compiler is a Babel plugin (and Vite/Next plugin wrapping it) that analyzes your JSX and detects values that would benefit from memoization. It then inserts the equivalent of useMemo / useCallback at build time. The runtime output behaves as if you'd manually wrapped every relevant value — but you didn't.

What it doesn't do

  • It doesn't change semantics. Your component still works the same; it just renders fewer times.
  • It doesn't replace useState / useEffect / useContext. Those are about state and side effects, not memoization.
  • It doesn't optimize away genuinely expensive computations. If your render does filterMassiveDataset(query), the Compiler memoizes the dataset reference but the filter still runs when the query changes. (Pair with useTransition or useDeferredValue for the perceived-speed win.)

How to enable

Add the babel-plugin-react-compiler to your build config. For Vite: install babel-plugin-react-compiler, add it to @vitejs/plugin-react's babel.plugins option. Restart dev server. Done.

The opt-in escape

If a specific component's behavior depends on identity-sensitive re-renders that the compiler shouldn't change, add the directive 'use no memo' as the first statement in the component. The Compiler skips it.

Stop reaching for useMemo defensively. Before the Compiler, the cost of NOT wrapping was a potential re-render; the cost of wrapping was a tiny memo allocation. People wrapped everything 'just in case.' With the Compiler enabled, defensive wrapping is noise. Write the natural code; let the build do the optimization.

Code

vite.config.ts — enabling the React Compiler·ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          // npm i -D babel-plugin-react-compiler
          ["babel-plugin-react-compiler", { /* options if needed */ }],
        ],
      },
    }),
    tailwindcss(),
  ],
});
Before vs after — what you wrote vs what runs·tsx
// What you write (clean, natural)
function Greeting({ name, tags }: { name: string; tags: string[] }) {
  const full = `Hello, ${name}!`;
  const sortedTags = [...tags].sort();
  const onClick = () => console.log(name);
  return (
    <div>
      <h1>{full}</h1>
      <TagList tags={sortedTags} onItemClick={onClick} />
    </div>
  );
}

// What the Compiler emits (conceptually) — memoized where it would have helped
function Greeting({ name, tags }: { name: string; tags: string[] }) {
  const full = $useMemo(() => `Hello, ${name}!`, [name]);
  const sortedTags = $useMemo(() => [...tags].sort(), [tags]);
  const onClick = $useCallback(() => console.log(name), [name]);
  return (
    <div>
      <h1>{full}</h1>
      <TagList tags={sortedTags} onItemClick={onClick} />
    </div>
  );
}

// You wrote the top. The compiler emitted the bottom. The bottom never
// re-creates the sorted array or the callback when name and tags are unchanged.

External links

Exercise

Enable the React Compiler in your bootstrap project. Pick a component that has useMemo / useCallback wrappers. Remove them. Run the app and verify behavior is unchanged. Open the React DevTools Profiler and confirm the component still re-renders the same number of times as before. The Compiler is doing the memo work behind the scenes.
Hint
If DevTools shows more re-renders than before, the Compiler may not be enabled — check the babel plugin is loaded (look for react-compiler in your built JS, or check the dev server logs).

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue
💛 by Ttoriwarm

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.