Skip to content

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

Closed
fresh3nough wants to merge 1 commit intomainfrom
fix/hof-wrapped-component-lint-35910
Closed

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

Conversation

@fresh3nough
Copy link
Owner

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: facebook#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
@fresh3nough
Copy link
Owner Author

Closing in favor of a PR against the upstream repo (facebook/react).

@fresh3nough fresh3nough closed this Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

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

1 participant