-
Notifications
You must be signed in to change notification settings - Fork 50.9k
Description
What kind of issue is this?
- React Compiler core (the JS output is incorrect, or your app works incorrectly after optimization)
- babel-plugin-react-compiler (build issue installing or using the Babel plugin)
- eslint-plugin-react-hooks (build issue installing or using the eslint plugin)
- react-compiler-healthcheck (build issue installing or using the healthcheck script)
Link to repro
Repro steps
When the use hook is called on an object that is not exactly the identifier React (e.g., an aliased import or any other object), the React Compiler produces incorrect output. The compiled code moves the hook call inside a conditional cache block, violating the Rules of Hooks. In contrast, other hooks like useState are compiled correctly regardless of the object name.
Steps to Reproduce
Input code:
import React from 'react'
function App() {
const v = React.use(); // ✅ works
return <div>{v}</div>
}
function App2() {
const [v] = React.useState(); // ✅ works
return <div>{v}</div>
}
// ---------------------
import ReactAlias from 'react'
// ❌
function App3() {
const v = ReactAlias.use(); // ❌ fails
// const v = someObj.use(); // ❌ also fails
return <div>{v}</div>
}
function App4() {
const [v] = ReactAlias.useState(); // ✅ works
// const v = someObj.useState(); // ✅ also works
return <div>{v}</div>
}Actual Output (compiled with React Compiler)
import { c as _c } from "react/compiler-runtime";
import React from "react";
function App() {
const $ = _c(2);
const v = React.use();
let t0;
if ($[0] !== v) {
t0 = <div>{v}</div>;
$[0] = v;
$[1] = t0;
} else {
t0 = $[1];
}
return t0;
}
function App2() {
const $ = _c(2);
const [v] = React.useState();
let t0;
if ($[0] !== v) {
t0 = <div>{v}</div>;
$[0] = v;
$[1] = t0;
} else {
t0 = $[1];
}
return t0;
}
// ---------------------
import ReactAlias from "react";
// ❌
function App3() {
const $ = _c(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const v = ReactAlias.use();
t0 = <div>{v}</div>;
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
}
function App4() {
const $ = _c(2);
const [v] = ReactAlias.useState();
let t0;
if ($[0] !== v) {
t0 = <div>{v}</div>;
$[0] = v;
$[1] = t0;
} else {
t0 = $[1];
}
return t0;
}Expected Output
For App3, the compiler should produce output similar to App, where the hook’s return value (v) is tracked as a dependency rather than the whole JSX element being cached unconditionally. The hook call should remain outside any conditional block to maintain the Rules of Hooks.
Additional Observations
- The issue occurs when
useis called on any object whose name is not exactlyReact. - Other hooks (e.g.,
useState,useEffect) are compiled correctly even when called on aliased imports. - The problem is specific to the
usehook; it appears that the compiler’s optimization forusedepends on the object being namedReact.
How often does this bug happen?
Every time
What version of React are you using?
19.2.0
What version of React Compiler are you using?
1.0.0