Skip to content

fix: detect setState in useEffect for anonymous component callbacks passed to HOFs#35943

Open
fresh3nough wants to merge 1 commit intofacebook:mainfrom
fresh3nough:fix/hof-wrapped-component-lint-35910
Open

fix: detect setState in useEffect for anonymous component callbacks passed to HOFs#35943
fresh3nough wants to merge 1 commit intofacebook:mainfrom
fresh3nough:fix/hof-wrapped-component-lint-35910

Conversation

@fresh3nough
Copy link

Summary

The react-hooks/set-state-in-effect ESLint rule was not detecting setState calls inside useEffect when the component was an anonymous callback passed to a higher-order function (e.g. const MyComponent = wrap(() => { ... })).

Root Cause

getFunctionName() in the compiler's Program.ts did not handle the HOF pattern where the parent is a CallExpression whose parent is a VariableDeclarator. This meant the anonymous function was never identified as a component and never compiled/validated by the lint rules.

Changes

  • compiler/.../Entrypoint/Program.ts: Add HOF pattern handling to getFunctionName() so const MyComponent = wrap(() => {}) resolves the function name to MyComponent
  • packages/eslint-plugin-react-hooks/src/shared/RunReactCompiler.ts: Add CallExpression to the mayContainReactCode heuristic so files with HOF-wrapped components are not skipped
  • packages/eslint-plugin-react-hooks/__tests__/ReactCompilerRuleTypescript-test.ts: Add test cases for both set-state-in-effect and prop mutation detection in HOF-wrapped components

Test Plan

All 5086 existing ESLint plugin tests pass, plus 4 new tests:

  • HOF-wrapped component prop mutation detection (immutability rule)
  • Direct component setState in effect detection (set-state-in-effect rule)
  • HOF-wrapped component setState in effect detection (set-state-in-effect rule)
  • Direct component without setState in effect (valid case)

Fixes: #35910

…assed to HOFs (facebook#35910)

The react-hooks/set-state-in-effect ESLint rule was not detecting
setState calls inside useEffect when the component was an anonymous
callback passed to a higher-order function (e.g. const MyComponent =
wrap(() => { ... })).

Root cause: getFunctionName() in the compiler did not handle the HOF
pattern (parent is CallExpression whose parent is VariableDeclarator),
so the anonymous function was never identified as a component and
never compiled/validated.

Changes:
- Add HOF pattern handling to getFunctionName() in Program.ts
- Add CallExpression to the mayContainReactCode heuristic in
  RunReactCompiler.ts so HOF-wrapped components are not skipped
- Add test cases for both set-state-in-effect and prop mutation
  detection in HOF-wrapped components

Fixes: facebook#35910
@meta-cla meta-cla bot added the CLA Signed label Mar 2, 2026
@Moses-main
Copy link

Hi @facebook team,

I'll fix the setState detection in useEffect. I have experience with:

  • React internals
  • Hooks implementation
  • Component patterns

My approach:

  1. Analyze the issue
  2. Fix the detection logic
  3. Add tests

Please assign!

Copy link

@codeCraft-Ritik codeCraft-Ritik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great attention to detail throughout the code.

@fresh3nough
Copy link
Author

Ty

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DevTools Bug]: react-hooks/set-state-in-effect misses setState in useEffect for anonymous component callbacks passed to HOFs

3 participants