Files
laurenandRaashish Aggarwal d083ec1da1 [compiler] Allow setState after await in effect functions (#36734)
`react-hooks/set-state-in-effect` flagged setState calls that happen
after an `await` inside an async function invoked from an effect.
Post-await code resumes in a microtask after the effect body has
returned, so the "synchronous setState cascades a render" rationale does
not apply; the lint was a false positive on a common data-loading shape
(15 reactions on the issue).

The fix exempts a setState only when it is *provably* post-await: a
forward must-dataflow over the HIR CFG computes the blocks that begin
after an await has executed on every path from the function entry
(optimistic initialization so loop back-edges do not pessimize the meet,
fixpoint to the greatest solution), plus an intra-block flag for
instructions after an Await in the same block. A setState reachable on
any await-free path still flags, so the conditional-await case remains
an error by design, with a fixture documenting that choice. Suppression
is sound under try/catch because HIRBuilder terminates blocks after each
instruction in a try region, and an awaited rejection also resumes in a
microtask.

Fixtures: post-await setState (event gone), setState before the first
await (still flags), setState after a conditional await (still flags).
First commit documents the false positive via the lint-mode logger
output, second removes it.

Builds on the approach in #36417 by @raashish1601, hardened from a
seen-await flag to the path-sensitive analysis above. Implemented
identically in the TypeScript compiler and the Rust port.

Verification: TS snap 1807/1807, Rust snap 1807/1807, cargo workspace
green, scoped TS-vs-Rust HIR parity harness green.

Closes #34905

---------

Co-authored-by: Raashish Aggarwal <94279692+raashish1601@users.noreply.github.com>
2026-09-22 10:26:59 -07:00
..