fix(compiler): React Compiler safety triage — 5 categories cleared
Cleared 4 rule buckets (37 violations, including 5 real bugs) and
silenced 1 informational bucket from the Next 16 / react-hooks v7
upgrade. Cleared rules promoted from `warn` back to `error` so new
regressions block CI.
Real bug fixes:
- `interest-contact-log-tab.tsx`: `useMemo` used for side effects
(5 setState calls inside a memo body); converted to `useEffect`.
- `PieChart.tsx`: cumulative `let angle` mutation in a render-phase
`map`; converted to `reduce` so the slice array is built without
re-assignment.
- `documents-hub.tsx`: `useMemo(() => ({ count: 0 }))` used as a
mutable drag counter; converted to `useRef`.
- `notes-list.tsx`: `Date.now()` read during render for note-edit
countdown (impure) → pinned to a `now` state ticked every 30s.
- `onboarding-checklist.tsx` / `user-profile.tsx` /
`user-settings.tsx`: `useEffect(() => void load(), [])` with the
`load` function declared AFTER the effect — relied on hoisting,
trips Compiler's "access before declared" rule. Declared inside
the effect.
Pattern fixes (intentional cache-via-ref → state or layout-effect):
- 6 `ref.current = x` writes during render moved into layout
effects (`use-realtime-invalidation`, `settings-form-card`,
`inbox`).
- 3 `ref.current` reads during render (search totals cache,
scanner file ref) rewritten to backed-by-state.
- `use-is-mobile.ts` rewritten on `useSyncExternalStore` to avoid
the SSR-then-rehydrate setState dance.
- `use-notifications.ts` rewritten to write socket pushes directly
into the React Query cache via `setQueryData`, removing a local
state mirror.
Rule config (`eslint.config.mjs`):
- `react-hooks/purity` → error (was warn, cleared)
- `react-hooks/set-state-in-render` → error (was warn, cleared)
- `react-hooks/immutability` → error (was warn, cleared)
- `react-hooks/refs` → error (was warn, cleared)
- `react-hooks/incompatible-library` → off (informational only)
- `react-hooks/set-state-in-effect` → warn (51 remaining, all the
useEffect→fetch→setState data-fetch pattern; migration to
useQuery tracked in BACKLOG)
Verified: tsc clean, eslint 0 errors / 69 warnings (down from 105),
vitest 1315/1315, next build green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,20 +8,26 @@ const eslintConfig = [
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
// React Compiler safety rules that ship with eslint-config-next@16 /
|
||||
// react-hooks@7. These flag setState-in-effect, ref-during-render,
|
||||
// and impurity patterns that the upcoming React Compiler will trip
|
||||
// on. They surfaced ~73 hits in the existing codebase on the
|
||||
// next-16 bump — all legitimate findings but a clean-up project
|
||||
// worth a dedicated triage pass, not a blocker for the dep
|
||||
// upgrade. Demoted to warnings so the suite stays visible without
|
||||
// turning every commit red. Tracked in docs/BACKLOG.md §G.
|
||||
// React Compiler safety rules shipped with eslint-config-next@16 /
|
||||
// react-hooks@7. Triage status (2026-05-12 sweep):
|
||||
// purity, set-state-in-render, immutability, refs — promoted
|
||||
// back to error after the existing hits were cleaned up; new
|
||||
// regressions block CI.
|
||||
// set-state-in-effect — left as warn. Many hits are the
|
||||
// useEffect→fetch→setState data-loading pattern that the
|
||||
// Compiler conservatively flags but can't refactor without
|
||||
// moving each call site to TanStack Query. ~50 admin-form
|
||||
// land sites tracked in docs/BACKLOG.md §G.
|
||||
// incompatible-library — informational only ("Compiler
|
||||
// skipped this file because of a non-Compiler-safe import").
|
||||
// No action needed; silenced to keep `pnpm lint` output
|
||||
// actionable.
|
||||
'react-hooks/purity': 'error',
|
||||
'react-hooks/set-state-in-render': 'error',
|
||||
'react-hooks/immutability': 'error',
|
||||
'react-hooks/refs': 'error',
|
||||
'react-hooks/set-state-in-effect': 'warn',
|
||||
'react-hooks/set-state-in-render': 'warn',
|
||||
'react-hooks/refs': 'warn',
|
||||
'react-hooks/immutability': 'warn',
|
||||
'react-hooks/purity': 'warn',
|
||||
'react-hooks/incompatible-library': 'warn',
|
||||
'react-hooks/incompatible-library': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user