- Published on
useDebounce Hook in React
- Authors

- Name
- Tails Azimuth
The Problem
When users type in a search box, you don't want to fire an API call on every keystroke. That's wasteful and slow.
The Solution
Here's a tiny useDebounce hook that delays a value update until the user stops typing:
import { useState, useEffect } from 'react'
export function useDebounce<T>(value: T, delay: number = 500): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value)
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedValue(value)
}, delay)
return () => clearTimeout(timer)
}, [value, delay])
return debouncedValue
}
Usage Example
function SearchBar() {
const [query, setQuery] = useState('')
const debouncedQuery = useDebounce(query, 300)
useEffect(() => {
if (debouncedQuery) {
fetch(`/api/search?q=${debouncedQuery}`)
}
}, [debouncedQuery])
return <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search..." />
}
#HTML Sample Code
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
</body>
</html>
SQL Sample Code
SELECT u.id, u.name, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.created_at >= '2026-01-01'
GROUP BY u.id, u.name
HAVING COUNT(o.id) > 5
ORDER BY order_count DESC
LIMIT 10;
Python Sample Code
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n: int) -> int:
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
if __name__ == "__main__":
for i in range(10):
print(f"fib({i}) = {fibonacci(i)}")
Go Sample Code
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
ch := make(chan int, 5)
for i := 1; i <= 5; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
ch <- n * n
}(i)
}
wg.Wait()
close(ch)
for v := range ch {
fmt.Println(v)
}
}
Rust Sample Code
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let sum: i32 = numbers.iter().filter(|&&x| x % 2 == 0).sum();
println!("Sum of evens: {}", sum);
}
Bash Sample Code
#!/usr/bin/env bash
set -euo pipefail
for file in *.log; do
lines=$(wc -l < "$file")
echo "$file has $lines lines"
done
JSON Sample
{
"name": "useDebounce",
"version": "1.0.0",
"keywords": ["react", "hooks", "debounce"],
"peerDependencies": {
"react": ">=17.0.0"
}
}
CSS Sample Code
.search-input {
width: 100%;
padding: 0.75rem 1rem;
border: 1px solid #d1d5db;
border-radius: 0.5rem;
transition: border-color 150ms ease-in-out;
}
.search-input:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25);
}
Why This Works
The useEffect clears the previous timer every time value changes, so the API call only fires after the user pauses typing for 300ms.
Drop this into any project — it'll save you from rate limits and improve UX instantly.