React
Components
- •Prefer composition over prop drilling — use children, render props, or context to pass behavior
- •Keep components focused — if a component handles multiple concerns, split it
- •Colocate related code (styles, types, helpers) with the component that uses them
- •Use named exports for components; match filename to component name
- •Derive state from props/other state instead of syncing with effects
- •Lift state only as high as needed — not higher
Hooks
- •Follow the Rules of Hooks: only call at the top level, only call from React functions
- •Extract custom hooks when logic is reused or when a component's hook logic gets complex
- •Keep dependency arrays accurate — never suppress the exhaustive-deps lint
- •Use
useReffor values that shouldn't trigger re-renders (timers, DOM refs, previous values) - •Prefer
useReduceroveruseStatewhen state transitions depend on previous state or involve multiple related values - •Avoid
useEffectfor things that can be computed during render — effects are for synchronization with external systems
Performance
- •Don't optimize prematurely — measure first with React DevTools Profiler
- •Use
memoonly when a component re-renders often with the same props and rendering is expensive - •Use
useMemo/useCallbackonly when passing values to memoized children or when computation is genuinely expensive - •Move static objects and arrays outside the component to avoid re-creating them on every render
- •Use
keyto reset component state intentionally; use stable, unique keys for lists (not array index)
Patterns
- •Handle loading, error, and empty states explicitly — don't assume the happy path
- •Use error boundaries to catch and handle render errors gracefully
- •Prefer controlled components for forms; use uncontrolled with
useRefonly when integrating with non-React code - •Use
childrenas the default composition mechanism before reaching for render props or compound components - •Avoid prop spreading (
{...props}) except on thin wrapper components where it's intentional