Quick reference for essential React Hooks with common pattern and usage example.
useState
Local component state that persist between re-render and triggers updates when changes.
Basic API
const [state, setState] = useState(initialSate)Immutable updates
Always create new objects and arrays instead of mutating state.
setForm({...form, name: "Aditya"})setTodos([...todos, setTodos])setTodos(todos.filter(t => t.id !== id))Updater functions
Use function for dependent updates to avoid stale state.
function Counter (){ const [count, setCount] = useState(0) const increment = () => setCount(c => c + 1) retrun <button onClick={increment}>{count}</button>}Deriving state
Calculate values during render instead storing them in state.
function OrderSummary({ items }) { const [discount, setDiscount] = useState(0) const subTotal = items.reduce((sum, item) => sum + item.price, 0) const total = subTotal - discount return <p>`Total: ${total}`</p>}State organization
Structure state to avoid contradictions and duplication. Group related state that changes together.
const [status, setStatus] = useState("idle")const [position, setPosition] = useState({x: 0, y: 0})Resetting state
Use key props to reset component state when data changes.
<Chat key={user.id} contact={person} />Updates Batched: Multiple setState calls in events are batched automatically
Stale Closure: Use adapter functions to avoid stale state
useContext
Share data across component tree without manually passing props through every level.
Basic API
const value = useContext(SomeContext)Sharing and updating data
Create context, provide values, and consume anywhere in component tree.
const ThemeContext = creteContext(null)function MyApp() { return ( <ThemeContext.provider value="dark"> <HeroSection/> </ThemeContext.provider> )}function Button() { const theme = useContext(ThemeContext) return <button className={theme}>Change theme</button>}No props drilling: skip intermediate component entirely
Single Source: Context value comes from nearest Provider above
useEffect
Escape hatch too syncronize with external systems and perform side effect after render.
Basic API
useEffect(setup, dependencies?)Event listeners
Subscribe to DOM event and cleanup on unmount.
useEffect(() => { const handleResize = () => setSize({ width: window.innerWidht, height: window.innerHeight}) window.addEventListener("resize", handleResize) return () => window.removeEventListener("resize", handleResize)}, [])External connections
Connect to external system and cleanup when done.
useEffect(() => { const connection = createConnection(registerId) connection.connect() return () => connection.disconnect()}, [registerId])After render: Effect run after DOM updates, not during
Cleanup required: Always cleanup subscriptions and timers
useRef
Escape hatch for mutable value and DOM references that persist across renders without re-rendering.
Basic API
const ref = useRef(initialvalue)DOM manipulation
Access DOM nodes imperative operations.
function SearchInput() { const inputRef = useRef(null) return ( <> <input ref={inputRef} /> <button onClick={() => inputRef.current.focus()}> Focus </button> </> )}Mutable values
Store value that persist across renders without triggering re-renders.
function SearchBox() { const searchCount = useRef(0) const handleSearch = () => { searchCount.current += 1 console.log(`Search performed ${searchCount} times`) } return <button onClick={handleSearch}>Search</button>}No re-render: Changing ref.current doesn't trigger updates
Imperative API: Focus, scroll, play/pause, measurement
Instance variable: Store times, subscriptions,previous values
Custom Hooks
Extract and reuse stateful logic between components with functions starting with "use".
State logic
Each component gets its own independent state.
function useCounter(initialValue = 0) { const [count, setCount] = useState(initialValue) const increment = setCount(c => c + 1) return { count, inrement }}Start with "use": Naming convention enables linter rule
Composition: Build complex Hooks from simple Hooks