When to use this
- A new or changed React component uses hooks (useEffect, useMemo, useCallback) and needs a correctness check.
- A component re-renders more than expected, or a `useEffect` behaves inconsistently.
- Not for a general code-style review of the component -- use code-review for that; this is React-specific correctness.
The skill file
Copy this verbatim. It's written in the SKILL.md format (YAML frontmatter + markdown instructions) that Claude Code, and increasingly other agent tools, read directly.
--- name: react-component-auditor description: Review a React component for hook-specific correctness bugs -- missing or incorrect useEffect dependencies, stale closures, and unnecessary re-renders from unstable references -- rather than general style. Use for components with non-trivial hook usage. --- # React Component Auditor ## useEffect dependency correctness - Does the dependency array include every value from component scope that the effect actually reads? A missing dependency means the effect captures a stale value from an earlier render (a stale closure) instead of the current one. - Conversely, is anything in the dependency array that shouldn't trigger a re-run (e.g. an object/function recreated every render, causing the effect to fire every render even though nothing meaningful changed)? - Does an effect with a subscription/timer/listener clean up correctly in its return function, so it doesn't leak or double-fire across re-mounts (especially with React 18 Strict Mode's double-invoke in development)? ## Stale closures outside useEffect - Does an event handler or callback capture a value from an earlier render via closure, when it should be reading current state (check whether it should use a ref, or the functional form of a state setter, instead)? ## Unnecessary re-renders - Is a new object/array/function literal created inline in JSX props on every render, defeating a child component's `memo`/`useMemo`/ `useCallback` optimization? - Is `useMemo`/`useCallback` used where the computation/function is cheap enough that memoizing it costs more than it saves (the dependency-array comparison itself isn't free)? ## Key prop correctness - In a list render, is `key` a stable, unique identifier for the item (not array index, unless the list is truly static and never reordered/ filtered)? ## Output Findings with the specific hook/line, what's wrong (stale closure / missing cleanup / unstable reference), and the concrete fix.
Installing it elsewhere
The frontmatter/body split above is Claude Code's convention. Here's how to carry the same instructions into other tools:
Save the file below verbatim (frontmatter included) at that path, project-local or in ~/.claude/skills/ for a user-level skill. Claude Code loads the name/description pair to decide when to pull it in, or you invoke it directly as /react-component-auditor.
Convert the YAML frontmatter to Cursor's rule format (description, globs, alwaysApply: false) and keep the markdown body as the rule content. Cursor surfaces it by description match, same idea as Claude Code's auto-load.
Codex CLI (and increasingly other agentic CLIs) read AGENTS.md at the repo root as always-on instructions. Paste the markdown body under a heading like ## {title}; for GitHub Copilot's coding agent, the equivalent file is .github/copilot-instructions.md.
Append the markdown body to .windsurfrules at the repo root. Windsurf treats the whole file as always-on context, so keep only the instructions you want applied on every request.
- Flagging every useEffect with a large dependency array as a problem without checking whether each dependency is actually needed.
- Recommending useMemo/useCallback everywhere instead of only where the render cost or referential-stability need actually justifies it.
- Missing that array-index keys break state on reorder/filter/insert, not just on obviously-dynamic lists.