Back to topics

Is React Compiler Usable Now, and What's the Principle?

React's design is simple: it's just

const ui = f(state)

But in the complex real world, there are too many things to consider when trying to idealize functional programming.

State sources are diverse, and state changes are often unexpected.

React had to create a bunch of APIs to handle various edge cases. But as the APIs grew, the mental burden increased. Then the React team proposed React Compiler, aiming to automatically optimize at compile time and reduce mental burden as much as possible.

Obviously, this also paves the way for future features. With React Compiler, there's more room for operations at compile time (e.g., automatically destructuring when a component declares prop types), allowing more new features to be added later.

So, is React Compiler usable now?

Yes, it is. And not only with React 19, but also with React 18 and 17.

Migrating Legacy Projects

Whether a legacy project can be directly used depends on whether the code follows the rules. If it follows the rules, it's usable. Meta has been using it in production for a long time.

You can use ESLint to check the code; if no errors are reported, it's likely fine. I know there are many legacy projects with messy code where people often disable ESLint. For such suspicious places, you can explicitly declare "use no memo" to skip React Compiler.

If you're still concerned about risks, you can create a new directory in your project, e.g., src/modern, and specify that only this directory uses React Compiler.

If creating a new directory is inconvenient, you can enable "opt-in" mode, where only components explicitly marked with "use memo" will be optimized by the React compiler.

In short, it's up to you. If you feel that writing useMemo/useCallback every day is too mentally taxing, then go ahead and adopt React Compiler.

For specific configuration methods, refer to the documentation: https://zh-hans.react.dev/learn/react-compiler/incremental-adoption

How It Works

Reference

playground

  1. Create an array $ and statically analyze how many cache slots the component needs.

  2. Store dependencies and templates in the array. If there are no dependencies, use a sentinel Symbol instead.

  3. On re-render, check if dependencies have changed. If they have, re-store the dependencies and template, then return the template. If not, return the cached template directly.

  4. No need for useMemo; simple conditional checks are enough.

Caveats

Currently, one major obstacle to not enabling React Compiler is that some projects use SWC instead of Babel for faster compilation. Since React Compiler currently exists as a Babel plugin, using Babel in an SWC project can be troublesome.

Also, it's not that you'll never use useCallback/useMemo again. It's still recommended to keep manual memoization for useEffect's dependency array and third-party library config objects.

In 2026, has your project adopted React Compiler? Feel free to leave a comment about any pitfalls you've encountered.