Creating a Custom useDebounce Hook in React.js
Debouncing is a programming practice that limits the rate at which a function can fire. It ensures that a function is only executed after a certain amount of time has passed since its last invocation. The timer resets if the function is called again during this wait time.
A typical example of this in React is a search input:
- Without debouncing: Function executes on every keystroke
- With debouncing: Function executes only after the user stops typing for a set period (e.g., 500ms)
It's a common problem in app development so one of the utilities I used to solve this problem is creating a custom useDebounce
hook.
useDebounce Hook
Here's my simple implementation of a clean and reusable debounce hook:
import { useState, useEffect } from 'react'; function useDebounce(value, delay = 500) { const [debouncedValue, setDebouncedValue] = useState(value); useEffect(() => { // Create a timeout to update the debounced value const timer = setTimeout(() => { setDebouncedValue(value); }, delay); // Clean up the timeout if the value changes or the component unmounts return () => clearTimeout(timer); }, [value, delay]); return debouncedValue; }
The hook works by:
First, accepting an initial value and delay duration (defaulting to 500ms). Then, maintaining a debounced state that updates only after the specified delay. We use the useEffect
to handle the timing logic. And then finally we need to properly clean up timeouts to prevent memory leaks
Working Example
Here's how I typically implement this hook in a search component:
function SearchComponent() { const [searchTerm, setSearchTerm] = useState(''); const debouncedSearch = useDebounce(searchTerm, 500); useEffect(() => { // API call happens only after the debounced value changes if (debouncedSearch) { searchAPI(debouncedSearch); } }, [debouncedSearch]); return ( <input type="text" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} placeholder="Search..." /> ); }
It's not just useful for search inputs, I use this hook for:
- Search inputs
- Window resize handlers
- Save drafts
- API calls on user input Plus whatever else I might not want to be called as fast as a person interacts with a page.
Creating a small library of hooks that you can drop into projects is useful for staying productive (and not reinventing the wheel every time you start a project).
Remember, while this implementation works well for most use cases, you might need to adjust the delay time based on your specific requirements. I typically use 500ms as a default, which can be modified depending on the use case and user experience needs.