Unnamed Skill
Apply when managing state, side effects, context, or refs in React functional components. **React 19+ Note**: React 19.x introduced new hooks for forms/actions (useActionState, useOptimistic, useFormStatus) and effect events (useEffectEvent in 19.2). Core hooks (useState, useEffect, useCallback, etc.) remain unchanged.
$ Installieren
git clone https://github.com/CoderMariusz/MonoPilot /tmp/MonoPilot && cp -r /tmp/MonoPilot/.claude/skills/react-hooks ~/.claude/skills/MonoPilot// tip: Run this command in your terminal to install the skill
name: react-hooks description: Apply when managing state, side effects, context, or refs in React functional components. React 19+ Note: React 19.x introduced new hooks for forms/actions (useActionState, useOptimistic, useFormStatus) and effect events (useEffectEvent in 19.2). Core hooks (useState, useEffect, useCallback, etc.) remain unchanged. version: 1.1.0 tokens: ~1100 confidence: high sources:
- https://react.dev/reference/react/hooks
- https://react.dev/reference/rules/rules-of-hooks
- https://react.dev/blog/2024/12/05/react-19
- https://react.dev/blog/2025/10/01/react-19-2 react_version: "18.2+, 19.x" last_validated: 2025-12-10 next_review: 2025-01-24 tags: [react, hooks, frontend, state]
When to Use
Apply when managing state, side effects, context, or refs in React functional components.
React 19+ Note: React 19.x introduced new hooks for forms/actions (useActionState, useOptimistic, useFormStatus) and effect events (useEffectEvent in 19.2). Core hooks (useState, useEffect, useCallback, etc.) remain unchanged.
Patterns
Pattern 1: useState with Objects
// Source: https://react.dev/reference/react/useState
interface FormState {
name: string;
email: string;
}
const [form, setForm] = useState<FormState>({ name: '', email: '' });
// Update single field (immutable)
setForm(prev => ({ ...prev, name: 'John' }));
Pattern 2: useEffect Cleanup
// Source: https://react.dev/reference/react/useEffect
useEffect(() => {
const controller = new AbortController();
async function fetchData() {
const res = await fetch(url, { signal: controller.signal });
setData(await res.json());
}
fetchData();
return () => controller.abort(); // Cleanup
}, [url]);
Pattern 3: useCallback for Stable References
// Source: https://react.dev/reference/react/useCallback
const handleSubmit = useCallback((data: FormData) => {
onSubmit(data);
}, [onSubmit]); // Only recreate if onSubmit changes
// Use in child: <Form onSubmit={handleSubmit} />
Pattern 4: useMemo for Expensive Computations
// Source: https://react.dev/reference/react/useMemo
const sortedItems = useMemo(() => {
return items
.filter(item => item.active)
.sort((a, b) => a.name.localeCompare(b.name));
}, [items]); // Recompute only when items change
Pattern 5: Custom Hook Pattern
// Source: https://react.dev/learn/reusing-logic-with-custom-hooks
function useDebounce<T>(value: T, delay: number): T {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debounced;
}
// Usage
const debouncedSearch = useDebounce(searchTerm, 300);
Pattern 6: useRef for DOM Access
// Source: https://react.dev/reference/react/useRef
const inputRef = useRef<HTMLInputElement>(null);
const focusInput = () => {
inputRef.current?.focus();
};
return <input ref={inputRef} />;
Pattern 7: useActionState for Forms (React 19+)
// Source: https://react.dev/blog/2024/12/05/react-19
import { useActionState } from 'react';
async function submitForm(prevState: any, formData: FormData) {
const name = formData.get('name');
// Perform async operation
return { success: true, name };
}
function MyForm() {
const [state, action, isPending] = useActionState(submitForm, null);
return (
<form action={action}>
<input name="name" disabled={isPending} />
<button disabled={isPending}>Submit</button>
{state?.success && <p>Success: {state.name}</p>}
</form>
);
}
Pattern 8: useEffectEvent for Non-Reactive Logic (React 19.2+)
// Source: https://react.dev/reference/react/useEffectEvent
import { useEffect, useEffectEvent } from 'react';
function Chat({ roomId, theme }) {
// Event function always sees latest theme, but doesn't trigger effect
const onConnected = useEffectEvent(() => {
showNotification('Connected!', theme);
});
useEffect(() => {
const connection = createConnection(roomId);
connection.on('connected', onConnected);
connection.connect();
return () => connection.disconnect();
}, [roomId]); // Only re-run when roomId changes
}
Anti-Patterns
- Hooks in conditions/loops - Call hooks at top level only
- Missing dependencies - Include all values used in effect/callback
- Over-using useMemo/useCallback - Use only when performance matters (profile first)
- Mutating state directly - Always use setter, spread for objects/arrays
- Async function as useEffect callback - Define async function inside, then call it
Verification Checklist
- Hooks at component top level (not in conditions)
- All dependencies listed in dependency arrays
- useEffect has cleanup for subscriptions/timers
- Custom hooks start with
useprefix - No direct state mutation
- useEffectEvent excluded from dependency arrays (React 19.2+)
Repository
