React Development
Guidance for building React applications with modern patterns.
Hooks Reference
Built-in Hooks
| Hook |
Purpose |
When to Use |
| useState |
Local state |
Simple values, toggles, form inputs |
| useReducer |
Complex state |
Multiple sub-values, state machines |
| useEffect |
Side effects |
Data fetching, subscriptions, DOM manipulation |
| useContext |
Consume context |
Theme, auth, global state |
| useRef |
Mutable reference |
DOM access, persist values across renders |
| useMemo |
Memoize value |
Expensive calculations |
| useCallback |
Memoize function |
Stable callbacks for child components |
| useLayoutEffect |
Sync DOM effects |
Measure DOM before paint |
| useId |
Unique IDs |
Accessibility, form labels |
Hook Rules
| Rule |
Why |
| Only call at top level |
Hooks rely on call order |
| Only call from React functions |
Components or custom hooks |
| Name custom hooks with "use" |
Convention for linting |
Component Patterns
| Pattern |
Use Case |
Key Concept |
| Presentational |
Pure UI, no logic |
Props in, JSX out |
| Container |
Data fetching, state |
Wraps presentational |
| Compound Components |
Related components sharing state |
Parent provides context |
| Render Props |
Share behavior |
Function as child |
| Custom Hooks |
Reusable stateful logic |
Extract from components |
| HOC |
Legacy pattern |
Prefer hooks instead |
State Management Decision
| Solution |
Best For |
Trade-offs |
| useState |
Component-local |
Simplest, prop drilling for sharing |
| useReducer |
Complex local state |
More boilerplate, predictable |
| Context |
Theme, auth, i18n |
Re-renders all consumers |
| Zustand |
Simple global |
Minimal API, good devtools |
| Redux Toolkit |
Complex global |
Powerful, more boilerplate |
| React Query/TanStack |
Server state |
Caching, background refresh |
| Jotai/Recoil |
Atomic state |
Fine-grained updates |
Key concept: Server state (API data) and client state (UI state) should be managed differently. Use React Query for server state.
useEffect Patterns
| Pattern |
Dependency Array |
Purpose |
| Run once |
[] |
Initial fetch, setup |
| Run on change |
[dep1, dep2] |
React to specific changes |
| Run every render |
(omit) |
Rarely needed |
| Cleanup |
Return function |
Subscriptions, timers |
Common Pitfalls
| Pitfall |
Solution |
| Infinite loops |
Include all dependencies, use useCallback |
| Stale closures |
Use refs or functional updates |
| Race conditions |
Cleanup flag or AbortController |
| Missing deps |
Trust the linter, refactor if needed |
Performance Optimization
| Technique |
When to Use |
Cost |
| React.memo |
Expensive child, frequent parent renders |
Shallow comparison |
| useMemo |
Expensive calculation |
Memory for cached value |
| useCallback |
Callback passed to memoized child |
Memory for function |
| Lazy loading |
Large components, routes |
Initial load vs waterfall |
| Virtualization |
Long lists (100+ items) |
Complexity |
Key concept: Don't optimize prematurely. Measure first with React DevTools Profiler.
Conditional Rendering
| Pattern |
Use Case |
| && |
Show/hide single element |
| Ternary |
Two alternatives |
| Early return |
Multiple conditions, cleaner |
| Switch/object map |
Many alternatives |
Form Handling
| Approach |
Use Case |
| Controlled |
Need validation, formatting |
| Uncontrolled (refs) |
Simple forms, performance |
| React Hook Form |
Complex forms, validation |
| Formik |
Legacy, full-featured |
Key concept: Controlled components store value in React state. Uncontrolled use DOM as source of truth.
Project Structure
| Directory |
Purpose |
| components/ui/ |
Generic, reusable (Button, Card) |
| components/features/ |
Feature-specific compositions |
| hooks/ |
Custom hooks |
| contexts/ |
React contexts + providers |
| pages/ or routes/ |
Route components |
| services/ or api/ |
API calls, data fetching |
| types/ |
TypeScript types |
| utils/ |
Pure helper functions |
Best Practices
| Practice |
Why |
| Keep components small (<100 lines) |
Readable, testable |
| Colocate related code |
Easier to maintain |
| Lift state only when needed |
Avoid unnecessary complexity |
| Use TypeScript for props |
Catch errors, better DX |
| Prefer composition over inheritance |
React's design philosophy |
| Extract custom hooks |
Reusable logic, testable |
Resources