Introduction
When building search features in React—such as searching for users, products, or posts—you may want to avoid triggering an API call every time the user types. Without control, a search input can make dozens of API calls per second, causing performance issues, unnecessary server load, and a poor user experience. The solution is debouncing, which adds a slight delay before triggering the search. If the user keeps typing, the timer resets, ensuring the search happens only when typing pauses. In this article, you will learn how to handle debounced search input properly in React using simple examples, custom hooks, and best practices.
What Is Debouncing?
Debouncing is a technique that delays a function call until after a specific amount of time has passed without new input.
Why Debouncing Is Useful
Reduces unnecessary API calls
Improves search performance
Provides a smoother user experience
Helps avoid rate-limiting or server overload
Simple Explanation
With a 500ms debounce delay, the search triggers only after the user stops typing for 500ms.
Basic Debounced Search Using setTimeout
Here’s how to use setTimeout with useEffect to debounce input.
Example
import { useState, useEffect } from "react";
function SearchBox() {
const [query, setQuery] = useState("");
const [debouncedQuery, setDebouncedQuery] = useState("");
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedQuery(query);
}, 500);
return () => clearTimeout(timer);
}, [query]);
return (
<>
<input
type="text"
placeholder="Search..."
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
<p>Searching for: {debouncedQuery}</p>
</>
);
}
How It Works
User types →
queryupdates instantlyTimer waits 500ms
If user continues typing, timer resets
debouncedQueryupdates only when typing stops
Using Debounced Value to Trigger API Calls
You can call the API inside another effect that depends on debouncedQuery.
Example
useEffect(() => {
if (!debouncedQuery) return;
fetch(`/api/search?q=${debouncedQuery}`)
.then(res => res.json())
.then(data => console.log(data));
}, [debouncedQuery]);
Benefits
API triggers only after delay
Prevents excessive server load
Creating a Custom useDebounce Hook (Reusable)
To avoid repeating debounce logic in every component, create a custom hook.
Custom Hook

Join the conversation! Your thoughts help the community grow.