mcpField
R
react-ban-use-effect

react-ban-use-effect

github.com/uinafDevelopment0253 installsUpdated 3d ago
Repository

About react-ban-use-effect

A React development skill for reviewing and replacing direct `useEffect` calls with alternatives suited to the behavior. It guides scoped migrations, legitimate external-system hooks, and lint and test verification.

Key features

  1. 01Classify direct effects and wrappers
  2. 02Prefer render, data, event, or keyed alternatives
  3. 03Define narrow external-system hooks
  4. 04Set scoped lint enforcement
  5. 05Verify changes with project gates

Use cases

  1. 01Review React code for unnecessary effects
  2. 02Migrate effects in a touched code area
  3. 03Document an external synchronization boundary

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/uinaf/agent-skills --skill react-ban-use-effect

After installing, type/react-ban-use-effectin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

evals/mechanical-effect-guardrail/
criteria.json
task.md
evals/vendor-map-widget/
criteria.json
task.md
references/
replacements.md
upstream.md

Details

From the project README

React Ban useEffect

Direct useEffect is an external-synchronization escape hatch. Components do not call it; a reviewed, domain-specific hook for a real external system may.

Scope

Effect replacement changes the touched behavior. Repository-wide lint enforcement is a separate task: apply it when requested or required by existing repository policy. A review request produces findings; an implementation request authorizes in-scope replacements and verification without another approval checkpoint.

Workflow

  1. Find direct imports, React.useEffect(...) namespace calls, and wrappers around useEffect in the touched surface.

  2. Classify each effect and replace it in this order of preference:

    1. render-time calculation
    2. server, loader, or framework data API
    3. the repository's server-state layer (for example a TanStack Query queryOptions factory with variables in the key and the signal passed through)
    4. event handler, action, or mutation
    5. keyed component boundary
    6. useSyncExternalStore
    7. reviewed domain-specific hook for a real external system

    If none fits, state the external synchronization contract before keeping an effect. Replacements covers the non-obvious cases.

  3. Preserve the repository's framework, data layer, lint shape, and dependency policy. Add a library only when the request or repository policy authorizes it; without a server-state layer, call the remaining effect a design gap.

  4. Run lint, type, and test gates plus the smallest real UI or hook check for the changed behavior.

Legitimate Effects

Put every legitimate effect in a hook named for its external system (a chat connection, a map SDK, a widget), in its own file. The hook owns setup and cleanup, takes its reactive inputs as parameters, and lists every value setup or cleanup reads. The component calling it stays effect-free. Prefer an existing repository hook.

Never:

  • write a generic wrapper that takes a callback and a caller-provided dependency array (useUpdateEffect(fn, deps), useAsyncEffect(fn, deps), useMountEffect(fn));
  • suppress react-hooks/exhaustive-deps;
  • use an exception hook to fetch server state, copy props into state, relay user actions, or hide a reset that belongs at a keyed boundary.

Enforcement

When enforcement is in scope, extend the repository's existing linter so it rejects both named useEffect imports and React.useEffect(...) calls. Allow only the named, reviewed integration-hook files, never a directory such as src/hooks/**, and never a generic wrapper; report the wrapper and its callers as violations to migrate. Keep the canonical local gate and CI on that same lint surface; agent guidance or optional scanners do not replace it. Do not use @latest diagnostic tools as durable enforcement.

In review, every new direct effect is a finding unless the change documents and proves a legitimate external-system boundary. Ask for a replacement, not dependency-array tuning.

Boundaries

  • Scope migrations to the touched or requested surface.
  • Leave useLayoutEffect, useInsertionEffect, framework lifecycle APIs, and non-React effect systems alone, including in lint rules, unless requested.
  • Apply performance primitives only for measured behavior or an established repository pattern.
  • Upstream attribution: upstream.

Comments

Markdown supported