[compiler] Fix `set-state-in-effect` validation for `React.useEffect`
Summary
I noticed that React.useEffect bypasses the set-state-in-effect validation, as shown below (or see this CodeSandbox).
// ✅ ESLint error reported (refer to: react-hooks/set-state-in-effect)
useEffect(() => setState(s => s + 1), []);
// ❌ No ESLint error, but it should have
React.useEffect(() => setState(s => s + 1), []);
Initially I thought this was an eslint-plugin-react-hooks issue, but later realized it's a Compiler-level bug.
The bug was in the callee extraction for MethodCall: it checked receiver (the React namespace) instead of property (the useEffect method). Since React is not an effect hook, the validation was skipped.
The fix changes instr.value.receiver to instr.value.property so that useEffect is correctly identified as an effect hook.
const callee =
instr.value.kind === 'MethodCall'
- ? instr.value.receiver
+ ? instr.value.property
: instr.value.callee;
How did you test this change?
-
Added a
React.useEffectcase toinvalid-setState-in-useEffect.js. -
Updated
invalid-setState-in-useEffect.expect.mdand checked the Logs: only oneCompileErrorat line 7, missingReact.useEffectat line 10. (See Commit 1) -
Fixed
ValidateNoSetStateInEffects.ts. -
Updated
invalid-setState-in-useEffect.expect.mdagain and checked the Logs: now twoCompileErrors are reported (line 7 and line 10). (See Commit 2) -
Ran and passed all tests in
compiler/packages/babel-plugin-react-compiler(yarn snap:ci).