Skip to content

build: React packages have no rules-of-hooks / exhaustive-deps linting #718

@bpowers

Description

@bpowers

Problem

The shared ESLint config (eslint.config.shared.js) wires up @eslint/js, @typescript-eslint, eslint-plugin-react, and eslint-config-prettier, but eslint-plugin-react-hooks is not loaded anywhere. As a result, none of the React-rendering packages (@simlin/app, @simlin/diagram, @simlin/serve-web, website) get any hooks linting at all.

This was discovered during a dependency audit: eslint-plugin-react-hooks was declared in src/app/package.json devDependencies but never referenced by any eslint config, so it has been removed as an unused dependency (branch dep-diet). Removing it makes the gap explicit rather than introducing it.

The reactConfig block in eslint.config.shared.js only spreads eslint-plugin-react's recommended rules:

const reactConfig = {
  files: ['**/*.tsx'],
  plugins: { react: reactPlugin },
  rules: { ...reactPlugin.configs.recommended.rules, ... },
};

There is no react-hooks plugin and no react-hooks/rules-of-hooks or react-hooks/exhaustive-deps rule.

Why it matters

The two react-hooks rules catch real bugs:

  • rules-of-hooks flags conditional / out-of-order hook calls that corrupt React's hook state and cause hard-to-diagnose runtime crashes.
  • exhaustive-deps flags missing/stale dependency arrays in useEffect/useMemo/useCallback, the source of a large class of stale-closure bugs.

Simlin's React surface (the diagram editor, app shell, serve web client) is exactly the kind of stateful, effect-heavy UI where these bugs hide. Today none of it is checked.

Components affected

  • eslint.config.shared.js (the missing plugin + rules)
  • @simlin/app, @simlin/diagram, @simlin/serve-web (src/simlin-serve/web), website -- the packages that lint .tsx files and would gain coverage

Suggested approach

  1. Add eslint-plugin-react-hooks as a devDependency to the packages that lint .tsx (or to the root, depending on how the shared config resolves plugins).
  2. Wire it into the reactConfig block in eslint.config.shared.js: register the react-hooks plugin and enable react-hooks/rules-of-hooks (error) and react-hooks/exhaustive-deps (warn or error).
  3. Run lint and fix whatever violations surface. exhaustive-deps in particular tends to surface a backlog on first adoption -- triage each (genuine stale-closure bug vs. intentional omission that warrants an inline disable with a comment) rather than blanket-disabling the rule.

This should be a deliberate enablement + cleanup effort, not a silent re-add of the dependency.

Discovery context

Identified during a dependency audit of the repo on branch dep-diet, while removing eslint-plugin-react-hooks from src/app/package.json as an unused dependency.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ciCI, build pipeline, test hygienefrontendInvolved the React-based Typescript frontend

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions