react
Modern React with hooks and functional components. Trigger: When creating components, implementing hooks, managing state, or optimizing.
SKILL.md
| Name | react |
| Description | Modern React with hooks and functional components. Trigger: When creating components, implementing hooks, managing state, or optimizing. |
name: react description: "Modern React with hooks and functional components. Trigger: When creating components, implementing hooks, managing state, or optimizing." license: "Apache 2.0" metadata: version: "1.0" type: framework skills: - a11y dependencies: react: ">=17.0.0 <19.0.0"
React Skill
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 section). - Complex state (4+ related values)? ->
useReducer. See hooks-advanced.md (useReducer Patterns section). - Side effect? ->
useEffectwith proper deps. See use-effect-patterns.md. - Data fetching? ->
useEffect+ AbortController. See use-effect-patterns.md (Async Patterns section). - Performance issue? -> Profile first with React DevTools. See performance.md.
- Expensive computation? ->
useMemo. See performance.md (useMemo section). - Callbacks to memoized children? ->
useCallback. See performance.md (useCallback section). - Shared state across components? -> Context API or lift state. See context-patterns.md.
- Compound component API? -> See context-patterns.md (Compound Components section).
- Form with validation? -> Controlled components. See forms-state.md.
- Multi-step form? -> Wizard pattern. See forms-state.md (Multi-Step Forms section).
- File upload? -> Controlled input + File API. See forms-state.md (File Uploads section).
- Large list (1000+)? -> Virtualization. See performance.md (List Rendering Optimization section).
- 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