You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, the React compiler memoizes parameters passed to hooks if those parameters are non-primitives. This behavior appears to be applied universally, regardless of whether the hook is a built-in (native) React hook or a custom one.
However, for most native hooks, this memoization is unnecessary. It results in increased output code size and adds runtime overhead without any meaningful benefit.
Examples
Input code using useRef:
constref=useRef({ value });
Compiled output:
lett1;if($[0]!==value){t1={ value };$[0]=value;$[1]=t1;}else{t1=$[1];}constref=useRef(t1);
Input code using useState:
const[state,setState]=useState({ value });
Compiled output:
lett2;if($[2]!==value){t2={ value };$[2]=value;$[3]=t2;}else{t2=$[3];}const[state,setState]=useState(t2);
In both examples, the memoization of the initial values passed to the native hooks is unnecessary.
This same pattern of memoization is also applied to other built-in hooks such as useReducer and useEffect
Expected behavior
The compiler should treat native hooks differently and avoid memoizing parameters when it's not needed. This would reduce both the generated code size and runtime overhead.
How often does this bug happen?
Every time
What version of React are you using?
19.1.0
What version of React Compiler are you using?
19.1.0-rc.1
The text was updated successfully, but these errors were encountered:
josephsavona
changed the title
[Compiler Bug]: unnecessary memoization of non-primitive arguments in native React hooks
[Compiler]: unnecessary memoization of non-primitive arguments in native React hooks
May 2, 2025
Thanks for posting about this. You're right that the inputs to builtin React hooks don't have to be memoized. However, it is not free to produce these values and memoization can still be beneficial. We'd want to run some benchmarking and experiments to see what the right tradeoff is here.
The actual change itself would be trivial, we already have infrastructure to mark function or hook declarations as not aliasing their argument (noAlias internally) which we could apply to the builtin hook declarations to stop memoizing their inputs. But again, we're not sure if this is actually the best tradeoff.
What kind of issue is this?
Link to repro
https://playground.react.dev/#N4Igzg9grgTgxgUxALhASwLYAcIwC4AEwBUYCASggGYA0JZAyngIZ4IEC+BVMEGBAchgJmcPAIDcAHQB2suBBlhCpBAz4I8ACzQyA5gQC8BABTEAbswA2Udh2REClmwgcyoGAEYIYnAJRGAHxEsgQECkqEwlRG9BTUZk7Wtv7SMmERygQA2sqsCHRkeEz5ALqxqiVsic4pHH5poQTCeLDpwE1h0TSdBHlsPelhfZpVCE0caZOysggAHjj4jpUa2roG0zIgHEA
Repro steps
Currently, the React compiler memoizes parameters passed to hooks if those parameters are non-primitives. This behavior appears to be applied universally, regardless of whether the hook is a built-in (native) React hook or a custom one.
However, for most native hooks, this memoization is unnecessary. It results in increased output code size and adds runtime overhead without any meaningful benefit.
Examples
Input code using
useRef
:Compiled output:
Input code using
useState
:Compiled output:
In both examples, the memoization of the initial values passed to the native hooks is unnecessary.
This same pattern of memoization is also applied to other built-in hooks such as
useReducer
anduseEffect
Expected behavior
The compiler should treat native hooks differently and avoid memoizing parameters when it's not needed. This would reduce both the generated code size and runtime overhead.
How often does this bug happen?
Every time
What version of React are you using?
19.1.0
What version of React Compiler are you using?
19.1.0-rc.1
The text was updated successfully, but these errors were encountered: