React
Hooks, functional components, state management, and performance optimization for React apps.
When to Use
Use when:
- Creating or refactoring React functional components
- Implementing hooks (useState, useEffect, useMemo, useCallback)
- Managing state, side effects, or performance optimization
- Building component composition patterns
Don't use for:
- Non-React JS (use javascript skill)
- React Native (use react-native skill)
- Redux (use redux-toolkit skill)
- Server-side frameworks (use astro or relevant framework skill)
Critical Patterns
✅ REQUIRED: Functional Components with Hooks
// CORRECT: Functional component with hooks
const Counter: React.FC = () => {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
};
// WRONG: Class component (legacy)
class Counter extends React.Component {
state = { count: 0 };
render() { /* ... */ }
}
✅ REQUIRED: Proper useEffect Dependencies
// CORRECT: All dependencies included
useEffect(() => {
fetchData(userId);
}, [userId]);
// WRONG: Missing dependencies (stale closures)
useEffect(() => {
fetchData(userId);
}, []); // userId missing
✅ REQUIRED: Stable Keys for Lists
// CORRECT: Unique IDs
{items.map(item => <li key={item.id}>{item.name}</li>)}
// WRONG: Array index (bugs on reorder/delete)
{items.map((item, index) => <li key={index}>{item.name}</li>)}
❌ NEVER: Conditionally Call Hooks
// WRONG: Breaks React rules
if (condition) {
const [value, setValue] = useState(0);
}
// CORRECT: Hooks at top level, conditional logic inside
const [value, setValue] = useState(0);
const shouldUse = condition ? value : defaultValue;
Decision Tree
Simple state (<3 values)?
→ useState — see hooks-advanced.md (useState Patterns)
Complex state (4+ related values)?
→ useReducer — see hooks-advanced.md (useReducer Patterns)
Side effect?
→ useEffect with proper deps — see use-effect-patterns.md
Data fetching?
→ useEffect + AbortController — see use-effect-patterns.md (Async Patterns)
Performance issue?
→ Profile first with React DevTools — see performance.md
Expensive computation?
→ useMemo — see performance.md (useMemo)
Callbacks to memoized children?
→ useCallback — see performance.md (useCallback)
Shared state across components?
→ Context API or lift state — see context-patterns.md
Compound component API?
→ see context-patterns.md (Compound Components)
Form with validation?
→ Controlled components — see forms-state.md
Multi-step form?
→ Wizard pattern — see forms-state.md (Multi-Step Forms)
File upload?
→ Controlled input + File API — see forms-state.md (File Uploads)
Large list (1000+)?
→ Virtualization — see performance.md (List Rendering Optimization)
Conditional rendering?
→ && for simple, ternary for if-else, early return for complex logic
Example
import { useState, useMemo } from 'react';
interface TodoProps {
items: string[];
}
const TodoList: React.FC<TodoProps> = ({ items }) => {
const [filter, setFilter] = useState('');
const filteredItems = useMemo(() =>
items.filter(item => item.toLowerCase().includes(filter.toLowerCase())),
[items, filter]
);
return (
<div>
<input value={filter} onChange={(e) => setFilter(e.target.value)} />
<ul>
{filteredItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
};
Edge Cases
Stale closures in useEffect: Include all dependencies or use functional setState: setState(prev => prev + 1).
useEffect cleanup: Return cleanup for subscriptions, timers, listeners to prevent leaks:
useEffect(() => {
const timer = setInterval(() => {}, 1000);
return () => clearInterval(timer);
}, []);
Ref vs State: useRef for values that don't trigger re-renders (DOM refs, mutable values). useState for values that update UI.
Batching: React batches setState in event handlers. In async code, use flushSync for immediate updates (rare).
Children prop: Use React.ReactNode type. For render props: {(data) => <Component data={data} />}.
Architecture patterns: Apply Clean Architecture/SOLID only when AGENTS.md specifies it, codebase uses domain/application/infrastructure folders, or user requests. See architecture-patterns SKILL.md.
Checklist
- Functional components with hooks (no class components)
- All useEffect dependencies declared
- Stable keys on list items (unique IDs, not indices)
- No conditional hook calls
- Cleanup returned from useEffect for subscriptions/timers
- useMemo/useCallback only where profiling shows need
- Controlled inputs for forms with validation
- Context split by update frequency to avoid unnecessary re-renders
Resources
- references/ -- hooks-advanced, use-effect-patterns, performance, context-patterns, forms-state
- https://react.dev/
- https://react.dev/reference/react