Skip to content

Conversation

@basitqayoom
Copy link

@basitqayoom basitqayoom commented Feb 9, 2026

Summary

Fixes #34905

The set-state-in-effect validation (ValidateNoSetStateInEffects) was incorrectly flagging setState calls that appear after an await expression inside async functions called from useEffect.

After an await, execution continues asynchronously in a microtask — meaning the setState call is no longer synchronous within the effect body and should not trigger this lint.

Root cause

In getSetStateCall(), the function walks through the HIR of the effect callback and returns the first setState call it finds, without distinguishing whether that call appears after an Await instruction.

Fix

Added Await instruction tracking within each block in getSetStateCall():

  • When an Await instruction is encountered, a seenAwait flag is set for the current block
  • Any subsequent setState call in the same block after an Await is skipped (not reported as synchronous)

This is a conservative fix scoped to intra-block tracking. Cross-block await dominator analysis can be added as a follow-up if needed.

How did you test this change?

Added 3 new test fixtures:

Fixture Expected Description
allow-setState-in-useEffect-after-await ✅ No error setState after await via useCallback + useEffect (exact issue repro)
allow-setState-in-useEffect-async-callback ✅ No error setState after await in nested async function inside useEffect
invalid-setState-in-useEffect-before-await ❌ Error reported setState before await is still correctly flagged

All existing tests continue to pass:

$ yarn snap -- -p "invalid-setState-in-useEffect*"
5 Tests, 5 Passed, 0 Failed

$ yarn workspace eslint-plugin-react-compiler test
Test Suites: 8 passed, 8 total
Tests:       31 passed, 31 total

…acebook#34905)

The `set-state-in-effect` validation was incorrectly flagging setState
calls that appear after an `await` expression inside async functions
called from useEffect. After an `await`, execution continues
asynchronously in a microtask, so the setState call is not synchronous
within the effect body.

This fix adds `Await` instruction tracking in `getSetStateCall()`. When
an `Await` instruction is encountered in a block, subsequent setState
calls in the same block are skipped since they execute asynchronously.

Test plan:
- allow-setState-in-useEffect-after-await: setState after await via
  useCallback + useEffect (exact issue repro) - no error
- allow-setState-in-useEffect-async-callback: setState after await in
  nested async function inside useEffect - no error
- invalid-setState-in-useEffect-before-await: setState before await is
  still correctly flagged - error reported

Fixes facebook#34905

Co-authored-by: Cursor <[email protected]>
@meta-cla
Copy link

meta-cla bot commented Feb 9, 2026

Hi @basitqayoom!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at [email protected]. Thanks!

@meta-cla
Copy link

meta-cla bot commented Feb 9, 2026

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@meta-cla meta-cla bot added the CLA Signed label Feb 9, 2026
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.

[Compiler Bug]: react-hooks/set-state-in-effect false positive on async function

2 participants