agentleFS
BK202503BK202503/open-claude-all/skills/react-hooks-review/SKILL.md

react-hooks-review

Skill7 starsChanged 4 months agoMITView on GitHub

Review React (functional component + hooks) code before you PR for common regressions. `useEffect` dependency-array bugs, stale closures in event handlers, `useState` set-with-stale-value, over-memoization, list `key` anti-patterns, async effect cleanup leaks, and Rules-of-Hooks violations that a lint pass missed. Triggers include "review this React code", "check my hooks", "why does my effect run twice", "am I using useMemo right".

The file

We split this skill into the rules it gives an agent

9 rules. About 0 are common, 5 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every value the effect body reads that is defined in component scope must appear in the deps.

    line 17
  2. Very specific:

    Do not disable react-hooks/exhaustive-deps to "make the warning go away".

    line 18
  3. Distinctive:

    Only useful when either (a) the memoized value is expensive to recompute, or (b) the value is passed to a memoized child or used as an …

    line 30
  4. Very specific:

    Do not blanket-wrap every helper function in useCallback.

    line 31
  5. Very specific:

    Never use array index as key for lists that can reorder, delete, or insert.

    line 34
  6. Distinctive:

    Use a stable ID from the data.

    line 35
  7. Very specific:

    Prefer AbortController and check signal.aborted before setState, or a mounted-flag ref pattern.

    line 39
  8. Distinctive:

    No hooks inside conditionals, loops, or early returns.

    line 42
  9. Distinctive:

    No hooks in event handlers or class components.

    line 43

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

react-hooks-review

Catches React regressions that ship green through TypeScript and eslint-plugin-react-hooks yet still cause production bugs. Runs before you open a PR.

What to check

1. useEffect dependency arrays

  • Every value the effect body reads that is defined in component scope must appear in the deps. Missing deps mean stale reads.
  • Do not disable react-hooks/exhaustive-deps to "make the warning go away". If the warning is wrong, that is usually a signal to lift the value out or use a ref.
  • Deps that are recreated every render (inline objects, arrays, functions) reset the effect every render. Wrap in useMemo / useCallback or move outside the component.

2. Stale closures in event handlers

  • A handler passed to a child at mount captures the values from that render. Later setX calls re-render, but the child still holds the old handler unless its props changed.
  • Fix by using useCallback with proper deps, or by using the functional updater form of useState.

3. useState functional updater

  • setCount(count + 1) in an async callback can lose updates. Prefer setCount(c => c + 1).
  • Same for arrays: setItems(items => [...items, x]), not setItems([...items, x]).

4. useMemo and useCallback: perf theater vs actual need

  • Only useful when either (a) the memoized value is expensive to recompute, or (b) the value is passed to a memoized child or used as an effect dep. Otherwise it costs memory plus a shallow compare per render.
  • Do not blanket-wrap every helper function in useCallback. That is noise.

5. List key prop

  • Never use array index as key for lists that can reorder, delete, or insert. React reuses component state across the wrong items.
  • Use a stable ID from the data. If none exists, add one on ingest, not on render.

6. Async effects: cleanup and cancellation

  • Any effect that starts an async request must cancel it in the cleanup. Otherwise a race can setState after unmount.
  • Prefer AbortController and check signal.aborted before setState, or a mounted-flag ref pattern.

7. Rules of Hooks (silent violations)

  • No hooks inside conditionals, loops, or early returns. Lint catches most cases. Watch for hooks called inside custom hooks that are themselves called conditionally.
  • No hooks in event handlers or class components.

8. Server component leak (React 19 / Next App Router)

  • Hooks in a component that ends up being a server component is a build error. Confirm the "use client" boundary and where the component is imported from.

Common failure patterns to grep for

  • useEffect(() => { fetch(...) }) with no cleanup and no deps.
  • key={index} in a .map() that renders form inputs or components with internal state.
  • setState(state + 1) inside setTimeout, Promise.then, or WebSocket.onmessage.
  • // eslint-disable-next-line react-hooks/exhaustive-deps without a comment explaining why.

When to invoke

Trigger when the user asks for a React review, mentions hook confusion, or opens a PR touching *.tsx / *.jsx files with hook calls.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.