Context
PR #1062 upgraded eslint-plugin-react-hooks 5 → 7. v7 folds the React Compiler rule set into recommended, which flags 67 pre-existing sites. Adopting these is a deliberate, codebase-wide refactor — not a dependency bump — so they were deferred in eslint.config.js (with an inline comment) to preserve the prior enforcement level and keep the upgrade green.
This issue tracks turning them back on, incrementally.
Deferred rules (currently off in eslint.config.js)
| Rule |
Sites |
What it catches |
react-hooks/set-state-in-effect |
33 |
setState called synchronously in an effect body (cascading renders) |
react-hooks/refs |
31 |
reading/writing refs during render |
react-hooks/preserve-manual-memoization |
3 |
manual useMemo/useCallback the compiler can't preserve |
react-hooks/immutability |
1 |
mutating values that should be immutable |
Also: react-hooks/exhaustive-deps is pinned to warn (its historical level under v5) — v7 raised it to error.
Suggested approach
Adopt one rule at a time, file-scoped:
- Flip a rule from
off → error in eslint.config.js.
pnpm lint to list the violations.
- Fix each (many
set-state-in-effect cases are legitimate and need a real refactor or a scoped // eslint-disable-next-line with a reason — don't blanket-disable).
- Repeat per rule. Remove the deferral comment once all four are back on.
Lowest-risk first: immutability (1), preserve-manual-memoization (3), then refs (31), then set-state-in-effect (33).
Source: the inline rationale block in eslint.config.js is the authoritative record.
Context
PR #1062 upgraded
eslint-plugin-react-hooks5 → 7. v7 folds the React Compiler rule set intorecommended, which flags 67 pre-existing sites. Adopting these is a deliberate, codebase-wide refactor — not a dependency bump — so they were deferred ineslint.config.js(with an inline comment) to preserve the prior enforcement level and keep the upgrade green.This issue tracks turning them back on, incrementally.
Deferred rules (currently
offineslint.config.js)react-hooks/set-state-in-effectsetStatecalled synchronously in an effect body (cascading renders)react-hooks/refsreact-hooks/preserve-manual-memoizationuseMemo/useCallbackthe compiler can't preservereact-hooks/immutabilityAlso:
react-hooks/exhaustive-depsis pinned towarn(its historical level under v5) — v7 raised it to error.Suggested approach
Adopt one rule at a time, file-scoped:
off→errorineslint.config.js.pnpm lintto list the violations.set-state-in-effectcases are legitimate and need a real refactor or a scoped// eslint-disable-next-linewith a reason — don't blanket-disable).Lowest-risk first:
immutability(1),preserve-manual-memoization(3), thenrefs(31), thenset-state-in-effect(33).Source: the inline rationale block in
eslint.config.jsis the authoritative record.