React Compiler Will Steal Your Job

May 29, 2024

React 19 is revolutionary

React 19 is ready for testing in production!
It is truly an exciting release. React's mental model is shifting, allowing us to more efficiently build faster and more user-friendly frontend apps for our clients. The new version offers a cleaner way to handle our everyday tasks like data fetching, error handling, and loading, while also getting rid of a lot of mental overhead and technical boilerplate code that were polluting our components. Say goodbye to all of your useMemo, useCallbacks, and a huge portion of your useStates!

React 19 provides us the tools to utilize the best aspects of both the server and client. It brings these two seemingly distant worlds together and allows us to easily compose them in the “React-way” we are so used to and love. I highly recommend Dan Abramov's blog on The Two Reacts which provides the mental model for these “two worlds”. If you're not familiar with React Server Components, I'll give you a small hint: this is the solution to Dan's question.

If you are interested in all the new features React 19 brings, I strongly recommend reading the React team's React 19 RC blog post.

Introducing React Compiler

Now, back to the point. One of the most interesting new features that was announced alongside React 19 is the React Compiler. What? A compiler for what exactly?

You might be aware of the useMemo hook already:


const Calendar = ({ year }) => {
  const currentYearEvents = useMemo(() => filterALotOfEvents(year), [year]);
  // …
}

Basically, we are memoizing the result of a very long operation that filters through many events. We definitely don't want to be rerunning that operation on every render unnecessarily, so we only rerun it if any of the values in the dependency array (in this case, [year]) change. Performance boost! We always love that.

This is how you would rewrite the above using React 19 with the React Compiler:


const Calendar = ({ year }) => {
  const currentYearEvents = filterALotOfEvents(year)
  // …
}
 

Wait a second, where is the memoization? That is just a basic Javascript assignment. It will rerun the function on every render!
If that was your reaction, you used to be right. This is where React Compiler comes in.

Why React Compiler?

The team at Meta realized that a huge amount of their component code was polluted with useMemo, useCallback, memo calls. That is only part of the problem. Debugging and tracking down all the ways we could memoize our components for performance boosts could take a lot of time and effort, and worse, it's an on-going effort. Your component will most likely change over time. New code comes, old code goes, and with each change, you risk breaking your “perfectly” memoized component.

React Compiler was created to solve these issues. It has an in-depth understanding of your React code and the “Rules of React”. The Rules of React are rules you must follow to write idiomatic React code. If you break these rules, you are surely doing something wrong and likely have bugs.

In summary, these are the rules of React:

  • Components should be pure. They should always produce the same output for the same input (props, state, context)
  • Run side effects outside of render as React might call it multiple times for the best UX. You should use event handlers, or useEffect as a last resort to handle side effects.
  • Don't mutate props and state.
  • Don't mutate values after passing them to JSX, or hooks.

If you follow these rules, React Compiler will parse through your code and memoize every value that requires it. Magic? Almost. The answer is computer science.

How was it done?

How does React Compiler do it? It is definitely not simple. The compiler is open sourced and the initial commit added a whopping 350k+ lines of code. The React team has been working on this for years, and even started from scratch after realizing some of their mistakes.

Abstractly, it reduces your React code to very simple instructions and applies its understanding of the Rules of React to automatically transform your code into an optimized, memoized version. Under the hood, the compiler doesn't actually use useMemo as it isn't as performant. It uses simple if-else statements to add and fetch memoized values.

React Compiler has been used in production for Instagram for a while, and according to the team at Meta, it has produced 2.5x faster interactions, 12% faster initial loads and navigation, with no increase in memory usage.

By extension, that means that the team at Meta wasn't perfectly memoizing their components, so chances are you weren't either. A compiler beat some of the most talented React engineers!

I guess all of us are losing our jobs then? Right?
Certainly, such an intelligent React writer that outperforms even Meta's employees in their own game will evolve and send us to the streets? Isn't this the same logic we applied to ChatGPT?

Conclusion

If we think about it, React Compiler is seemingly producing perfect output code to solve a subset of issues we had. In the future, who is to say we won't combine AI with such concepts and be able to give a general problem text input, and it outputs perfect React code that solves the problem while understanding all the rules of React.

Possible? Sure. Probable? That is a different story. Although I love the idea of telling AI to create a billion-dollar Instagram competitor and for it to just spit out a perfect result, I think it's a bit more realistic to believe that a lot of brilliant people will have to come together and solve many problems to produce that for the foreseeable future.

Both React Compiler and generative AI tools are the result of brilliant people leveraging computer science concepts to solve repetitive and tedious tasks. In essence, they take an input, run those inputs on complex rules and algorithms, and produce an output. This simple chain of events allows us to produce successful and very impressive results for a lot of our well-known issues and tasks.

At the end of the day, we are problem solvers. It's a huge win that we are given the tools that allow us to spend more time actually producing value by solving problems for our clients, rather than debugging and optimizing our code for hours. Thank you, Meta.

Although I am totally bummed out that I won't be able to wow my coworkers by optimizing some of our slow components with manual useMemo and useCallback calls anymore, I'm excited to replace that time with creating better products for the world, one line at a time.