Critical Patterns
Custom Hooks (REQUIRED)
// ✅ ALWAYS: Extract reusable logic into custom hooks function useUser(userId: string) { const [user, setUser] = useState<User | null>(null); const [loading, setLoading] = useState(true);
useEffect(() => { fetchUser(userId).then(setUser).finally(() => setLoading(false)); }, [userId]);
return { user, loading }; }
// ❌ NEVER: Duplicate logic across components
Component Composition (REQUIRED)
// ✅ ALWAYS: Prefer composition over prop drilling function Dashboard({ children }: { children: React.ReactNode }) { return <div className="dashboard">{children}</div>; }
// Usage <Dashboard> <Sidebar /> <MainContent /> </Dashboard>
Memoization (WHEN NEEDED)
// ✅ Use useMemo for expensive calculations const sortedItems = useMemo(() => items.sort((a, b) => a.name.localeCompare(b.name)), [items] );
// ✅ Use useCallback for stable function references const handleClick = useCallback((id: string) => { setSelected(id); }, []);
Decision Tree
Need shared state? → Use Context or Zustand Need server state? → Use React Query / SWR Need form handling? → Use React Hook Form Need expensive calc? → Use useMemo Need stable callback? → Use useCallback Need DOM access? → Use useRef
Code Examples
Controlled Form
function LoginForm() { const [email, setEmail] = useState(""); const [password, setPassword] = useState("");
const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); login({ email, password }); };
return ( <form onSubmit={handleSubmit}> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} /> <button type="submit">Login</button> </form> ); }
Error Boundary
class ErrorBoundary extends React.Component<Props, State> { state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
render() { if (this.state.hasError) { return <FallbackUI />; } return this.props.children; } }
Commands
npx create-react-app myapp --template typescript npm run dev npm run build npm run test