Frontend

React Compiler: You'll Stop Copy-Pasting useMemo Without Knowing Why

Equipe Blueprintblog6 min
React Compiler: You'll Stop Copy-Pasting useMemo Without Knowing Why

Every React developer reaches a point where they start throwing useMemo and useCallback at everything — not because they understood it, but because the component was slow and it seemed like the right thing to do. React Compiler 1.0 is here to end that.


You know this code:

js
const discountedPrice = useMemo(() => {
  return product.price * (1 - discount);
}, [product.price, discount]);

const handleClick = useCallback(() => {
  addToCart(product.id);
}, [product.id]);

const ProductCard = React.memo(({ product, onAdd }) => {
  // ...
});

It works. Sort of. But you probably don't know which of those memoizations actually make a difference — and which ones are there out of collective superstition. What if the dependency list is wrong? What if you forgot one? What if the child component doesn't use React.memo and all that work was pointless?

That's the problem React Compiler 1.0 solves. Not partially — it takes over that entire job for you.


What the React Compiler actually is

It's a tool that runs at build time — not at runtime. Before your code reaches the browser, the compiler analyzes it, understands the data flow of each component, and automatically inserts memoization in the right places.

Think of it this way: you write code the way you always have. Clean, direct, without worrying about optimization. The compiler reads everything, understands what changes and what doesn't, and transforms the code before building.

The difference from what you did manually? The compiler can memoize across conditional paths — things that human useMemo simply can't reach. If a component has an early return before a heavy computation, it knows that path doesn't need memoization. You couldn't express that with hooks.

Released in October 2025 at React Conf, React Compiler 1.0 went stable after months of beta. It was battle-tested in production on Meta's major apps before going public — and now has stable support in Next.js 16, Vite, and Expo.


Before and after in practice

The same product component, with and without the compiler:

Before — manual and verbose:

js
function ProductCard({ product, discount }) {
  const price = useMemo(
    () => product.price * (1 - discount),
    [product.price, discount]
  );

  const handleAdd = useCallback(() => {
    addToCart(product.id);
  }, [product.id]);

  return (
    <div>
      <p>{price}</p>
      <button onClick={handleAdd}>Add to cart</button>
    </div>
  );
}

After — clean, same result:

js
function ProductCard({ product, discount }) {
  const price = product.price * (1 - discount);

  function handleAdd() {
    addToCart(product.id);
  }

  return (
    <div>
      <p>{price}</p>
      <button onClick={handleAdd}>Add to cart</button>
    </div>
  );
}

The second component looks like 2018 React. But in production, with the compiler enabled, it has the same performance guarantees as the first — or better. The compiler does the invisible work.


The numbers that matter

Meta didn't release the compiler based on theory. They used it in production first.

Result
Initial load12% faster — Meta Quest Store
Interactions2.5× faster after adoption
Render time20–30% reduction — Sanity Studio

Sanity Studio compiled 1,231 out of 1,411 components and saw a 20 to 30% reduction in render time and latency. Not an artificial benchmark — real product, in production, with real users.


How to enable it

If you're on Next.js 16, you already have stable support. Just enable it:

ts
// next.config.ts
const nextConfig = {
  reactCompiler: true,
};

export default nextConfig;

In Vite, via Babel plugin:

ts
// vite.config.ts
import react from "@vitejs/plugin-react";

export default {
  plugins: [
    react({
      babel: {
        plugins: ["babel-plugin-react-compiler"],
      },
    }),
  ],
};

Works from React 17 — you don't need to be on React 19 to start using it.


useMemo and useCallback still exist — just with a different role

Here's the detail most articles gloss over: you don't delete every useMemo in your project.

The compiler handles automatic memoization in general. But there's one specific case where you still control it manually: when a value is a useEffect dependency and you need reference stability.

js
// This useMemo still makes sense
const config = useMemo(() => ({
  timeout: props.timeout,
  retries: props.retries,
}), [props.timeout, props.retries]);

useEffect(() => {
  connect(config);
}, [config]); // config needs to be stable

Outside those cases, the compiler takes care of it. The practical rule: write clean React, without worrying about memoization. Only add useMemo or useCallback when a useEffect needs a stable dependency.

One real warning: the compiler assumes you follow React's rules — no direct state mutation, no side effects in wrong places. If your code breaks those rules, the compiler optimizes based on the assumption you aren't — and bugs become harder to track down. Before enabling, run eslint-plugin-react-hooks with the compiler preset.


Incremental adoption — not a big bang

The React Compiler is not a migration. You don't need to rewrite anything.

The React team's recommendation is simple: enable the compiler, run your end-to-end tests, and observe. If a component has compatibility issues, you can opt it out individually with a directive:

js
function LegacyComponent() {
  "use no memo"; // this component is excluded from the compiler
  // ...
}

This is rare in practice — but it exists as an escape hatch for cases where the compiler and legacy code don't play well together.


What changes in your day-to-day

  • Write clean React — no preventive useMemo, no precautionary useCallback.
  • The compiler optimizes at build time — automatic memoization, more precise than manual.
  • useMemo still has a place — only when useEffect needs a stable dependency.
  • Incremental adoption — enable, test, adjust. It's not a rewrite.
  • Supported in Next.js 16 and Vite — one line of config to get started.
  • Works from React 17 — no need to migrate to React 19 first.

References

Article tags

Related articles

Get the latest articles delivered to your inbox.

Follow Us: