React Hooks
How to Create a useDebounce Hook in React & Next.js
Optimizing search inputs and heavy operations is crucial for web performance. In this guide, we will build a professional useDebounce custom hook.
The Problem
When a user types in a search bar, an input event fires on every single keystroke. If you trigger an API request on every event, you will spam your server with unnecessary requests.
The Solution: Debouncing
Debouncing ensures that a function only runs after a certain period of inactivity. This means the API call will only trigger after the user has stopped typing for a set amount of time.
Step 1: Implement the Hook
Create the following custom hook to manage the delayed value:
import { useEffect, useState } from "react";/*** A custom hook that returns a debounced version of the provided value.* @param {any} value - The value to debounce.* @param {number} delay - The delay in milliseconds.*/export function useDebounce(value, delay) {const [debouncedValue, setDebouncedValue] = useState(value);useEffect(() => {const timer = setTimeout(() => {setDebouncedValue(value);}, delay);// Cleanup the timer if the value changes before the delay is reachedreturn () => {clearTimeout(timer);};}, [value, delay]);return debouncedValue;}
Step 2: Using the Hook in a Component
Now, let's see how to use this hook in a real-world scenario, such as a search input:
'use client'import { useDebounce } from "@hooks/useDebounce";import React, { useState } from "react";const SearchComponent = () => {const [value, setValue] = useState("");// This value will only update after 500ms of no typingconst debouncedSearch = useDebounce(value, 500);return (<div className="container mx-auto flex flex-col gap-2 mt-10 p-4 border rounded-lg"><label className="font-bold">Search Input:</label><inputclassName="border p-2 rounded"value={value}onChange={(e) => setValue(e.target.value)}placeholder="Type to search..."/><div className="mt-4 space-y-2"><div className="flex items-center gap-2"><span className="text-gray-500">Raw Value: </span><span className="font-mono">{value}</span></div ><div className="flex items-center gap-2"><span className="text-blue-600 font-semibold">Debounced Value: </span><span className="font-mono font-bold">{debouncedSearch}</span></div ></div></div>);};export default SearchComponent;
Summary
- Performance: Reduces the number of unnecessary function calls/API requests.
- Efficiency: Great for search bars, window resizing, and auto-save features.
- Clean Code: Decouples the input state from the expensive logic.