Use when writing or modifying React components, planning React features, or working with .jsx/.tsx files - provides modern React patterns with TypeScript, hooks usage, component composition, and common pitfalls to avoid
Provides modern React patterns with TypeScript, hooks, and component composition guidance.
npx claudepluginhub ed3dai/ed3d-plugins-testingThis skill inherits all available tools. When active, it can use any tool Claude has access to.
react-testing.mduseEffect-deep-dive.mdModern React development using functional components, hooks, and TypeScript. This skill guides you through React workflows from component creation to testing.
Core principle: Components are functions that return UI. State and effects are managed through hooks. Composition over inheritance always.
REQUIRED SUB-SKILL: Use ed3d-house-style:howto-code-in-typescript for general TypeScript patterns. This skill covers React-specific TypeScript usage only.
Functional components only. Use interface for props, avoid React.FC:
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
export function Button({ label, onClick, disabled }: ButtonProps) {
return <button onClick={onClick} disabled={disabled}>{label}</button>;
}
Event typing: React.MouseEvent<HTMLButtonElement>, React.ChangeEvent<HTMLInputElement>. Children: React.ReactNode.
useState for simple state:
const [count, setCount] = useState(0);
// Always use functional updates when new state depends on old
setCount(prev => prev + 1); // Good
setCount(count + 1); // Avoid - can be stale in closures
useReducer for complex state: When state has multiple related pieces that update together, or next state depends on previous state in complex ways.
State management decision framework:
useEffect for external systems only (API calls, subscriptions, browser APIs). NOT for derived state.
Critical rules:
Common pattern:
useEffect(() => {
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(res => res.json())
.then(data => setData(data));
return () => controller.abort(); // Cleanup
}, []);
For comprehensive useEffect guidance (dependencies, cleanup, when NOT to use, debugging), see useEffect-deep-dive.md.
Children prop: Use children: React.ReactNode for wrapping components.
Custom hooks: Extract reusable stateful logic (prefer over duplicating logic in components).
Compound components: For complex APIs like <Select><Select.Option /></Select>.
Render props: When component controls rendering but parent provides template.
ALWAYS use codebase-investigator first to find existing test patterns. Common approaches: React Testing Library, Playwright, Cypress.
See react-testing.md for comprehensive guidance.
Profile before optimizing. Use useMemo, useCallback, React.memo only when measurements show need. React 19 compiler handles most memoization automatically.
| Excuse | Reality |
|---|---|
| "useEffect is fine for derived state" | Calculate derived values directly. useEffect for derived state causes extra renders and bugs. |
| "React.FC is the standard way" | Community moved away from React.FC. Use explicit function declarations with typed props. |
| "Cleanup doesn't matter for short operations" | Memory leaks are real. Always cleanup subscriptions, timers, and abort fetch requests. |
| "Missing dependencies is fine, I know what I'm doing" | Stale closures cause bugs. Always include all dependencies. Fix the root cause, don't lie to the linter. |
| "useCallback with all dependencies is correct" | Including state in deps creates new function every render AND stale closures. Use functional setState updates instead. |
| "This is Functional Core because it's pure logic" | Hooks with state are Imperative Shell or Mixed. Only pure functions without hooks are Functional Core. |
| "Array index as key is fine for static lists" | If list ever reorders, filters, or updates, you'll get bugs. Use stable unique IDs. |
| "Mutating state is faster" | React won't detect the change. Always create new objects/arrays. |
| Task | Pattern |
|---|---|
| Props | interface Props {...}; function Comp({ prop }: Props) |
| State update | setState(prev => newValue) when depends on current |
| Fetch on mount | useEffect(() => { fetch(...); return cleanup }, []) |
| Derived value | Calculate directly, NOT useEffect |
| List render | {items.map(item => <Item key={item.id} />)} |
React.FC in new codeuseEffect with state as only dependencykey={index}state.value = xany type for props or event handlersWhen you see these, refactor before proceeding.
You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation.