FrontendReactCustom HooksReact HooksTypeScriptFrontend

Building Custom React Hooks: Patterns and Real-World Examples

Learn to build reusable custom React hooks with practical patterns for data fetching, local storage, media queries, and form state.

Abdur Razzak

Abdur Razzak

Full-Stack Web Developer

September 1, 2024 9 min read

Why Custom Hooks?

Custom hooks let you extract and reuse stateful logic between components without changing the component tree. Before hooks, sharing stateful logic required render props or higher-order components — both of which add component nesting and complexity. A custom hook is simply a JavaScript function whose name starts with 'use' and that calls built-in React hooks inside it.

useLocalStorage: Persistent State

The useLocalStorage hook persists React state to localStorage automatically. Initialize state from localStorage on mount, and sync changes back to localStorage on every update. Handle JSON serialization and parsing, and protect against SSR environments where localStorage is not available. This hook is useful for user preferences, theme selection, and form draft saving.

useFetch: Data Fetching with Abort

A useFetch hook wraps the browser's fetch API with loading, error, and data states. Critically, use an AbortController and clean it up in the useEffect return function to cancel in-flight requests when the component unmounts. This prevents the 'Cannot update state on unmounted component' warning that causes memory leaks in React apps.

useDebounce: Rate-Limited Inputs

Debouncing delays a function call until a specified time has passed since the last invocation. The useDebounce hook returns a debounced value that only updates after the delay. Use it for search inputs to avoid firing an API request on every keystroke — instead, only fetch when the user pauses typing for 300-500ms. This reduces API calls by 90% on typical search interfaces.

useMediaQuery: Responsive JavaScript

The useMediaQuery hook listens to CSS media queries from JavaScript using the window.matchMedia API. This is useful when you need to conditionally render components based on screen size (not just style them). Unlike CSS-only solutions, useMediaQuery gives you a boolean in JavaScript that you can use in your component logic — for example, to render a mobile menu instead of a desktop nav.

Testing Custom Hooks

Test custom hooks with the renderHook utility from @testing-library/react. Wrap hooks that need context providers in a wrapper option. Use act() to wrap state updates and async operations. Test the hook's initial state, its behavior after interactions, and edge cases like empty responses or network errors. Well-tested hooks can be shared across projects as an internal npm package or module.

Share this article

All posts
#React#Custom Hooks#React Hooks#TypeScript#Frontend
Abdur Razzak — Full Stack Web Developer

Let's Connect

Follow My Developer Journey