Bug: [eslint-plugin-react-hooks] incorrectly reports an error when hook is called outside of a loop.
The following code triggers an ESLint error with the rule eslintreact-hooks/rules-of-hooks stating:
"React Hook 'useState' may be executed more than once. Possibly because it is called in a loop. React Hooks must be called in the exact same order in every component render."
However, the hook useState is not inside the loop, and there is no reason for the error to be thrown.
React version:
React 19.0.0 (latest stable) eslint-plugin-react-hooks 5.1.0 (latest stable)
Steps To Reproduce
- Create a functional component with
useStatehook. - Add a
forloop inside the component (but outside the hook). - Run the ESLint with the
eslint-react-hooksplugin enabled.
const Component = () => {
const [state, setState] = useState(0);
for (let i = 0; i < 10; i++) {
console.log(i);
}
return <div></div>;
};
Link to code example:
https://codesandbox.io/p/devbox/8dlj6f
Run npm run lint
The current behavior
ESLint throws an error about useState potentially being called multiple times, even though it is not in a loop.
The expected behavior
No ESLint error should be thrown, as useState is not inside the loop, and should follow the rule of hooks correctly.
We're seeing what appear to be false positives on our CI as well: https://github.com/keycloak/keycloak/actions/runs/12190763028/job/34008503162?pr=35684
Similarly (but having react 18), having a for loop in the body of a functional component, even if it is unrelated to hooks, causes the linter to report that all hooks within that component with may be executed more than once error.
I've added the following code to the valid array in packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js:
{
code: normalizeIndent`
// valid because the loop does not change the number of times the hook is called
const Component = () => {
const [state, setState] = useState(0);
for (let i = 0; i < 10; i++) {
console.log(i);
}
return <div></div>;
};
`,
},
The test fails (but it should work). If I rollback this change: https://github.com/facebook/react/pull/28714/files#diff-5649cc9bc31063c1139ad0f91e98add9c77f641281cba934123db8aeade0b97eL298
The test starts passing (but 8 other use-cases start failing). So we need to make some changes that get all the tests working I think.
I'll try to look in to the code and get this use-case working: https://github.com/skratchdot/react/commit/e4daf2634e752ee63c06422f7427f931a0bb0cdf
Thanks for the reports, folks.
I think we need to handle do/while a bit differently then. I have a few ideas from my past work on #28714, let me push a PR.
Fix in https://github.com/facebook/react/pull/31720
Thanks @tyxla ! Since it was a regression, is it planned to release a patch version of eslint-plugin-react-hooks soon ?
@xfournet I'm not part of the React core team, so I can't tell, but let's summon some folks who were involved with https://github.com/facebook/react/pull/28714.
cc @mofeiZ and @josephsavona for review
While waiting for the fix to be published, downgrading to [email protected] is a workaround.
Will there be a patch release soon with this bug fix?
npm install eslint-plugin-react-hooks@next works for me
Considering there has been a fix landed for 2 months now, would it be possible to get a patch release to get this out there?