About React Compiler
October 24, 2025

Overview
Hi, recently I have a chance to take a look at React Compiler. Why? Cuz it's just release the first stable version here. The beta version is available for a while, but until now I step my foot into it. Let's see why we have this concept!
How React currrently rerender?
Current rule
React is the UI library, which give supply to user well and up-to-date interface. What does that mean? That means whenever you interact with the UI (clicking the button, hover to the field, or dragging a widget, ...), the UI should reflect all of the related part immidiately, else stay the same, which we call re-render.
The re-render in React has rules, as we might know so far:
- The state change
- The props change
- Parent component rerender
And when at least one of these happened, the component rerenders, not only for the component itself, but also all the child components (if any). If seeing this as the tree, which the affected component is the root, the process keeps going until it reaches all the leaf of the tree.
This should be normal, i agree. But the problem happens when there exist some children is heavy computed. First render is fine, but if this repeatedly render unnecessarily, the app will become slow.
What we have been doing
One of the solutions for this we use memoization. React.memo will be the first thing we think about. This is the highest level memoize by component. As we wrap the component with this, everytime rerender, it checks for its props. If the props has no change, it'll skip the rerender. Else if at least one prop change, it trigger rerender as normal.
It's cool (for primitive), but what if the props is non-primitive (object, array, function)? It creates new reference everytime, and when compare, even when by value it's not change but by reference it does. The component will be rerener anyways. This is where useMemo and useCallback jump in.
Their job is to keep the reference of non-primitive stay the same. useMemo is for array and object, where useCallback is for function. Whenever the props has those type, we need to wrap them with useMemo and useCallback so that React.memo works as expected.
But the problem is ...
This seems easy, yes. But when the tree grow, not only 2, 3 levels but more. Now sometime the props drill deep down under, and we need to keep track of the memoized one, and even some new, and for sure, sometime we just lost. It's a lot of effort to do this, then we at the crossroad:
- keep doing what we do, the complication grows
- not memoize at all, idle but not optimized performance
- memoize everything, the repo will be a mess of those "optimize support"
React Compiler
Yes, this is what React team offers for solving this problem. They transpile your current code, to the one that auto memoize almost everything for you. So as you might think, React.memo, useMemo and useCallback will no longer needed. Let's see my conclusion at the end of this.
How they works
It's will be long session, but let's check a simple example like this:
As usual, we will memoize data and onClick, but here is what React Compiler did:
Something new appears. Let's take a look:
- c: we might understand is cache (as an array), we react compiler save the previous computed value
- _c(1): array of 1 element, here is where we save the computed component at $[0], which is temperary saved at t0
- Symbol.for("react.memo_cache_sentinel"): it's the flag to check if the element is initialized or not.
And let's see what they are doing:
- Hoist
onClicksince it just pure function, for instead of creating every render of Parent, it just created once, and be used every component. - Check if the component is cached, if yes use it, else compute and cached.
- Instead of hoisting data, the data should be scoped, that's why it's inside the compute block.
It's nice, not only memoize it by saving inside cache, but it also do hoisting if possible. But what if, the function depends on the data, here is the interesting part.
Now, let's see the output of compiler:
Same process, but now we can see React Compiler from topdown, check if the dependency is cache, and do the computation if needed. And it needs 3 slots for caching: data, onClick and Component. I believe React Compiler can do more, but so far for the concept I think is is so enough.
Implementation
Installation
Following this doc, we need to
If you are using Babel for compiling, let's add this plugin to the configuration, remeber add the target option if you are not using version 19 of React (18 for example):
Now we checking for the compatible by running:
This will check:
-
How many components can be optimized by the compiler
-
If the Rules of React are followed.
-
If there are any incompatible libraries.
Checking if the installation works
If alls good, let's check if the application work as expected. By checking the re-render process by ticking Highlight updates when components render inside React Developer Tools.
And when you check The Component tree, it has Memo tag
Congrats, you are implemented this successfully!
Can it replace all React memoized?
The optimization will be handled automatically by the React Compiler, so it's should be safe for us if we remove useMemo and useCallback. I tried, most of them are good, but there still something that manual takes place:
Function as dependency of useEffect
For example, checking out this case:
If myFunction is inside dependency array of useEffect, the myFunction still need to be memoize with useCallback. I follow the thread of disscussion here, but the problem is still there without any solution or hotfix, so keeping the useCallback or useMemo for this.
External library (as Jodit)
In this case, the React Compiler compile the editor as pure component, it will not be rendered again if the content change, so the onChange and onBlur can not be triggered to update the content. Let's add at the top:
Adding this, but if the config has no useMemo, the config will be re-created and re-render everytime the editor change, so we will lose the focus everytime we type anything. Keeping useMemo for this case, to manually handle.
Conclusion
All of this, is for adding the option to your crossroad, the 4th one. Im not telling you this is the best option, since nothing is the best option for everything. But if you want new experience when you can spend less care for memoize, welcome. Else, you want to self handle everything for more control and less tool dependence, manual is the option for you. Anyways, hope we are all have a quick look at the concept of this.
Happy coding!
Table of Contents