React logoReact ADVANCED

React Custom Hooks

React custom hooks cheat sheet with patterns for state management, data fetching, debounce, and reusable logic with code examples.

20 min read
reactcustom-hookshooksuseEffectuseStatedata-fetchingperformanceutilities

Custom Hook Fundamentals

Learn the fundamentals of creating reusable custom hooks, from basic patterns to advanced composition techniques

Creating Custom Hooks

Master the art of creating reusable custom hooks for state management, side effects, and logic encapsulation

jsx
📄 Example
🟢 Always prefix custom hooks with "use" to follow React conventions
💡 Custom hooks let you extract and reuse stateful logic between components
⚡ Return consistent data types from your hooks for predictable behavior
📌 Custom hooks can call other hooks, enabling powerful composition
⚠️ Follow the Rules of Hooks: only call at top level, not in conditions
state-managementreusabilitycompositionbest-practices

Advanced Hook Patterns

Explore advanced patterns including hook composition, factory hooks, and complex state management

jsx
⏱️ Use debounce for search inputs and API calls
🔄 Implement cleanup in effects to prevent memory leaks
📱 Use media query hooks for responsive behavior

Data Fetching Hooks

Build robust data fetching hooks with loading states, error handling, caching, and request cancellation

API Integration Hooks

Build production-ready data fetching hooks with caching, error handling, retries, and optimistic updates

jsx
🚀 Implement request cancellation to prevent memory leaks
💾 Use caching to reduce redundant API calls
⚡ Add retry logic with exponential backoff for reliability

Utility & Performance Hooks

Create utility hooks for common tasks like local storage, debouncing, and performance optimization

Performance Optimization Hooks

Optimize React app performance with debouncing, throttling, memoization, and lazy loading hooks

jsx
👁️ Use Intersection Observer for lazy loading and animations
📋 Implement clipboard functionality with fallbacks
⌨️ Create keyboard shortcuts for better UX

Browser & Storage Hooks

Sync React state with localStorage, media queries, and theme

useLocalStorage

State that persists to localStorage with cross-tab sync

jsx
💡 Lazy init reads from localStorage once — no re-parse on every render
📌 The `storage` event fires in OTHER tabs only — gives you cross-tab sync
⚠️ Guard for SSR (typeof window) — Next.js will crash without it
🎯 Wrap in try/catch — quota errors and private mode both throw
storagestatepersistence

useMediaQuery

Subscribe to a CSS media query — responsive logic in JS

jsx
💡 useSyncExternalStore is the right primitive — no tearing, SSR-safe
⚡ Return false from getServerSnapshot so SSR renders the desktop view by default
📌 Honor `prefers-reduced-motion` and `prefers-color-scheme` — free accessibility wins
🎯 Wrap breakpoint strings in a `breakpoints` map so they stay in sync with Tailwind
responsivecssa11y

Interaction & Lifecycle Hooks

Practical hooks for debounce, click-outside, event listeners, and prior values

useDebouncedValue & useDebouncedCallback

Debounce a changing value or a callback — search inputs, autosave

jsx
💡 useDebouncedValue for derived state; useDebouncedCallback for side effects
⚡ The fnRef pattern keeps the debounced wrapper stable as fn changes
📌 Always cancel the pending timer on unmount — stale fires can crash
🎯 Typical delays: 200–300ms for search, 500–800ms for autosave
performancedebouncesearch

useClickOutside & useEventListener

Dismiss menus/popovers and attach typed event listeners safely

jsx
💡 Use mousedown (not click) — fires before focus/blur and feels snappier
⚡ The handlerRef pattern avoids re-binding listeners every render
📌 touchstart needs { passive: true } to avoid scroll-blocking warnings
🎯 useEventListener is the typed, cleanup-safe primitive for any DOM event
eventsdomui

usePrevious & useIsFirstRender

Track the previous value of a variable, detect the first render

jsx
💡 usePrevious is two lines: a ref + effect — no library needed
📌 useUpdateEffect skips the mount run — perfect for "fire on change" UX
⚡ useIsFirstRender returns true exactly once per component lifetime
🎯 Combine usePrevious + a CSS class for cheap value-change flash effects
lifecyclepatterns

useIntersectionObserver

Detect when an element enters the viewport — lazy load, infinite scroll

jsx
💡 IntersectionObserver beats scroll listeners — browser-optimized, throttled by default
⚡ `rootMargin: "200px"` pre-fetches BEFORE the element is on screen
📌 freezeOnceVisible prevents re-triggering for one-shot animations
🎯 Sentinel + this hook is the cleanest infinite-scroll pattern in React
scrolllazy-loadperformance