skills/react-ban-use-effect/SKILL.md
Ban direct `useEffect` in React code. Use when writing, refactoring, reviewing, or migrating React components or hooks that import, call, add, or replace direct `useEffect`; when an agent reaches for effects for derived state, fetching, event reactions, resets, or external sync; or when adding lint/agent rules for a no-direct-useEffect policy. Do not use for ordinary React work with no effect smell, non-React code, or legitimate effect architecture outside React.
npx skillsauth add uinaf/skills react-ban-use-effectInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Default stance: do not import or call useEffect directly in React components. Treat effects as an escape hatch for synchronizing with external systems, not as the default place to put render, event, data, or reset logic.
useEffect imports and calls.Use the highest applicable layer:
useSyncExternalStore, approved mount sync, or a reviewed dependency-aware external-sync exceptionIf none of these fit, stop and explain why the code truly needs an effect instead of adding direct useEffect.
Prefer existing repo wrappers. If the repo has no standard, add mount-only sync close to shared React hooks:
import { useEffect } from "react";
export function useMountEffect(effect: () => void | (() => void)) {
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(effect, []);
}
Good mount uses are browser API setup, DOM focus/scroll integration, and third-party widget lifecycles. Prefer useSyncExternalStore for external stores or browser values that change over time. If an external system must resync when a prop or state value changes, require an explicit reviewed exception or dependency-aware wrapper that keeps dependencies honest. Do not use wrappers to hide dependency problems, fetch server state, copy props into state, or relay user actions.
For new policy work, prefer the repo's existing ESLint shape. The usual rule is no-restricted-imports against useEffect from react, with the message pointing developers to declarative replacements and approved wrappers. Also block namespace calls such as React.useEffect(...) with no-restricted-syntax or a custom rule. Allow shared wrapper files as the only direct-import/call exceptions. If the repo already uses another lint shape, preserve that local convention.
If the repo uses React Doctor, prefer its native rules for effect smells (no-fetch-in-effect, no-derived-state-effect) in addition to the import ban. Keep suppressions line-local and rule-specific.
For reviews, treat new direct useEffect as a finding unless the diff also introduces a clear, reviewed exception. Ask for a replacement plan rather than dependency-array tuning.
For upstream provenance and uinaf tailoring notes, use references/upstream.md.
useLayoutEffect, framework lifecycle APIs, and non-React effect systems alone unless requested.Core sources and the broader alternatives bibliography live in references/alternatives.md.
development
Independently audit existing code, diffs, branches, or pull requests by spawning mandatory concern-specific reviewer subagents, then synthesizing their evidence into a ship decision. Use when triaging PR risk, deciding whether someone else's change is safe to ship, or following up after runtime proof. Produces a `ship it` / `needs review` / `blocked` verdict. Do not use to self-check a change you just authored.
testing
Set up or align a repository's GitHub collaboration and delivery surface: repo settings, branch/ruleset policy, PR and security templates, Actions hardening, GitHub Environments, release workflows, and deploy workflows. Use when standardizing GitHub setup for repos, CI/CD, publishing versioned packages, or deploying running apps; route app deploy details to deploy references and package publish details to release references.
tools
Run structured Codex/Claude autoreview closeout for uncommitted changes, branch/PR diffs, or single commits: choose the target, run the bundled review helper, validate findings, and rerun focused tests until clean. Use when asked for autoreview, Codex review, Claude review, automated PR review, second-model review, or merge-readiness review.
tools
Run Codex's built-in `codex review` closeout: pick local/branch/commit targets, run the helper or raw review command, filter findings, and rerun focused tests plus review until clean. Use when the user asks for Codex review, autoreview, second-model review, merge-readiness review, or parallel tests plus review before final, commit, ship, or PR update.