React Compiler is a build-time tool that automatically memoizes components and hooks. It removes the need for manual useMemo, useCallback, and React.memo in most code. It is stable, tested in production, and optional: you enable it through your build tool rather than installing a new runtime library.
What it optimizes
The compiler focuses on two jobs. It skips cascading re-renders, so a parent update no longer re-renders every child by default. It also memoizes expensive calculations that happen inside components and hooks.
- It optimizes components and hooks.
- It does not memoize every standalone function.
- Its memoization is not shared between different components.
For example, when a parent's state changes, only the parts of the tree that actually depend on the new values re-render, instead of every child below the parent.
For a calculation that lives in a plain helper outside any component, the compiler leaves it alone, and you may still want to profile that code separately.
How to enable it
Install the compiler as a development dependency. It is designed for React 19 and supports React 17 and 18 through configuration.
npm install -D babel-plugin-react-compiler@latestThe compiler is a Babel plugin. It must run first in the plugin list so it sees the original source before other transforms.
module.exports = {
plugins: ["babel-plugin-react-compiler"],
};Vite users can use the reactCompilerPreset from version 6 of @vitejs/plugin-react, and Next.js enables the compiler through its configuration from version 15.3.1 onward. Check the current React Compiler installation guide for the exact wiring of your build tool. When you already have a Babel config, place the plugin ahead of any preset or plugin that rewrites JSX.
What changes in your code
Before the compiler, a list component carries three layers of manual memoization to stay fast.
import { memo, useCallback, useMemo } from "react";
const ExpensiveList = memo(function ExpensiveList({ items, onSelect }) {
const sorted = useMemo(() => sortItems(items), [items]);
const handleSelect = useCallback((id) => onSelect(id), [onSelect]);
return (
<ul>
{sorted.map((item) => (
<li key={item.id} onClick={() => handleSelect(item.id)}>
{item.title}
</li>
))}
</ul>
);
});Here sortItems returns a sorted copy of the items array, and the inline arrow is a small wrapper around the handler. With the compiler enabled, you write the same component without the wrappers.
function ExpensiveList({ items, onSelect }) {
const sorted = sortItems(items);
return (
<ul>
{sorted.map((item) => (
<li key={item.id} onClick={() => onSelect(item.id)}>
{item.title}
</li>
))}
</ul>
);
}The compiler tracks the values that flow into each component and reuses the previous output when nothing relevant changed, which covers the memo, useMemo, and useCallback work from the first version. Compiled components show a sparkle (✨) badge in React DevTools so you can confirm it is running. The result is invisible to users but measurable in the Profiler, where the compiled component stops appearing in commits whose inputs did not change.
Compiler versus manual memo
| Task | Manual memoization | React Compiler |
|---|---|---|
| Skip child re-renders | Wrap the child in memo | Applied automatically |
| Cache a value | Wrap it in useMemo | Applied automatically in components and hooks |
| Cache a function | Wrap it in useCallback | Applied automatically in components and hooks |
| Code to maintain | Wrappers and dependency arrays | Plain component code |
Adopt it carefully
The compiler relies on your code following the Rules of React. When a component or hook breaks those rules, the compiler skips optimizing it and the companion ESLint plugin flags the file. Install eslint-plugin-react-hooks at its latest version, where the compiler rules live in the recommended-latest preset, and fix the reported violations over time.
You can also opt a single component out with the "use no memo" directive while you fix a problem, then remove the directive. The ESLint plugin reports each component the compiler would skip, so fixing a report directly increases the number of optimized components.
The compiler is meant to be adopted incrementally, which is why measuring before you change anything still applies. For existing code, keeping memo and useMemo and useCallback in place is fine, since removing them can change compiled output.
Rune AI
Key Insights
- React Compiler memoizes components and hooks automatically at build time.
- It is stable, optional, and enabled through your build tool.
- Install babel-plugin-react-compiler and let it run first.
- Compiled components show a sparkle badge in React DevTools.
- You can keep manual memo calls or remove them after testing.
Frequently Asked Questions
Is React Compiler stable?
Do I need to remove my existing useMemo and useCallback calls?
Conclusion
React Compiler performs the memoization work that you would otherwise do by hand with memo, useMemo, and useCallback. Enable it through your build tool, follow the Rules of React so it can optimize safely, and reserve manual memoization for the few places where you need precise control.
More in this topic
How to Build a Dropdown Menu in React
Build a React dropdown menu with the ARIA menu button pattern. Handle open and close, keyboard arrows, and clicks outside the menu.
How to Animate React Components with Motion
Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.
Headless UI Components Explained: Logic Without Locked Styling
Understand headless UI components and how libraries like Radix give you unstyled, accessible behavior that you style yourself.