fix(frontend): enforce real react-hooks lint and clear the warning backlog (#21) #180
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/21-real-react-hooks-lint"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #21. First of the v3.5.0 (Frontend Platform & PWA) milestone.
Why
eslint.config.jswas deliberately dependency-free, which forced two workarounds:EventSource,FileReader, …), which is whyno-undef/no-unused-varscould only be warnings.react-hooksname, purely so the source's// eslint-disable-next-line react-hooks/exhaustive-depsdirectives resolved instead of erroring on an unknown rule.Net effect: hooks rules were never actually enforced. The tell was in the lint output itself — 3 warnings of "Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps')". The stub reported nothing, so directives suppressing real violations looked redundant.
What changed
Added
@eslint/js,eslint-plugin-react-hooks, andglobalsas devDependencies (exact-pinned, matching the rest of the file), then:globalspackage. This alone fixes everyno-undef, and letsno-undef/no-unused-varscome from@eslint/jsrecommended at error — a real merge gate.Config decision worth reviewing
react-hooks is configured with
rules-of-hooks+exhaustive-depsexplicitly, rather than by spreading the plugin'srecommendedpreset. As of eslint-plugin-react-hooks v7,recommendedenables 16 rules — 13 of them React Compiler rules (static-components,use-memo,immutability,purity,set-state-in-effect, …), mostly aterror. This issue asks for exactly the two rules above; adopting the compiler rule set is a separate, much larger piece of work. Rationale is documented in the config. Suggest filing that as its own issue.The 5 real findings from enabling exhaustive-deps
RecordingDashboardrefreshSessionre-created every render and used by the SSE effect — a naive dep-array fix would rebuild the EventSource on every renderidCampaignDetailuser?.idto seed character inputs but omitted itWikiArticle(owners)article.entrywhile listing only sub-propertiesWikiArticle(save)handleSaveArticlereadsisGmforgm_notesbut omitted itCampaignPlanningcampaignIddep (unused in body;handleLoadalready re-creates on it)The
RecordingDashboardone is the clearest argument for this issue: that trap was invisible while the stub was in place.Mechanical cleanup
Unused
Reactimports (React 19 automatic JSX runtime), dead bindings, 2 emptycatch {}blocks made explicit with reasons, and 2 useless regex escapes ([^\w\s\-]→[^\w\s-],[^\)]→[^)]— both behaviour-preserving; the characters are already literal in those positions).Verification
All run in node:20, matching CI:
npm run lint→ exit 0, no output (was 31 warnings; 33 problems once the real rules were on)npx vitest run→ 69/69 passing, 11 filesnpx vite build→ succeedsnpm ciagainst the regenerated lock in a clean dir → OK (CI usesnpm ci)The build still warns "chunks larger than 500 kB" — that's #105 (route-level code splitting), next in this milestone.
🤖 Generated with Claude Code