React
Quick Start
import { useState } from 'react';
function Counter() { const [count, setCount] = useState(0);
return ( <button onClick={() => setCount(c => c + 1)}> Count: {count} </button> ); }
Features
Feature Description Guide
Hooks useState, useEffect, custom hooks HOOKS.md
TypeScript Props, state, event typing TYPESCRIPT.md
State Zustand, Context, useReducer STATE.md
Forms React Hook Form, Zod validation FORMS.md
Testing Vitest, Testing Library TESTING.md
Performance memo, useMemo, useCallback, Suspense PERFORMANCE.md
Common Patterns
Typed Component with Props
interface UserCardProps { user: { id: string; name: string; email: string }; onEdit: (user: UserCardProps['user']) => void; onDelete: (id: string) => void; }
function UserCard({ user, onEdit, onDelete }: UserCardProps) { return ( <div className="user-card"> <h3>{user.name}</h3> <p>{user.email}</p> <button onClick={() => onEdit(user)}>Edit</button> <button onClick={() => onDelete(user.id)}>Delete</button> </div> ); }
Custom Hook for Data Fetching
function useFetch<T>(url: string) { const [data, setData] = useState<T | null>(null); const [loading, setLoading] = useState(true); const [error, setError] = useState<Error | null>(null);
useEffect(() => { let cancelled = false;
async function fetchData() {
try {
const res = await fetch(url);
const json = await res.json();
if (!cancelled) setData(json);
} catch (e) {
if (!cancelled) setError(e as Error);
} finally {
if (!cancelled) setLoading(false);
}
}
fetchData();
return () => { cancelled = true; };
}, [url]);
return { data, loading, error }; }
Form with Validation
import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod';
const schema = z.object({ email: z.string().email(), password: z.string().min(8), });
function LoginForm() { const { register, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(schema), });
const onSubmit = (data: z.infer<typeof schema>) => { console.log(data); };
return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...register('email')} /> {errors.email && <span>{errors.email.message}</span>} <input {...register('password')} type="password" /> {errors.password && <span>{errors.password.message}</span>} <button type="submit">Login</button> </form> ); }
Workflows
Component Development
-
Define props interface with TypeScript
-
Create component with hooks
-
Extract reusable logic to custom hooks
-
Add error boundaries for fault isolation
-
Write tests with Testing Library
State Management Decision
Local state only -> useState Complex local state -> useReducer Shared across tree -> Context + useReducer App-wide state -> Zustand/Redux Server state -> TanStack Query
Best Practices
Do Avoid
Use functional components Class components
Extract custom hooks Duplicating effect logic
Memoize expensive computations Premature optimization
Handle loading/error states Assuming success
Use keys for lists Index as key for dynamic lists
Project Structure
src/ ├── App.tsx ├── main.tsx ├── components/ # Reusable UI components ├── hooks/ # Custom hooks ├── pages/ # Route components ├── stores/ # State management ├── services/ # API calls ├── utils/ # Helper functions └── types/ # TypeScript types
For detailed examples and patterns, see reference files above.