useDebounceCallback
A hook that debounces a callback function to limit its execution frequency. This custom hook provides a way to optimize performance by controlling how often a function is executed.
Implementation
export function useDebounceCallback<T extends (...args: any[])=> any>(
callback: T,
delay: number
): (...args: Parameters<T>) => void {
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
const callbackRef = useRef(callback);
useEffect(() => {
callbackRef.current = callback;
}, [callback]);
return useCallback((...args: Parameters<T>) => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
timeoutRef.current = setTimeout(() => {
callbackRef.current(...args);
}, delay);
}, [delay]);
}
Usage
Debounce API calls when user types in search input
export default function App() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
const handleResize = useDebounceCallback(() => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight
});
console.log('Window resized!'); // To see when the callback actually fires
}, 500);
// Attach the event listener
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [handleResize]);
return (
<div>
<h3>Try resizing your window!</h3>
<p>Width: {windowSize.width}px</p>
<p>Height: {windowSize.height}px</p>
</div>
);
}
Parameters
callbackT extends (...args: any[]) => anyrequired
The function to debounce
delaynumberrequired
The delay in milliseconds before executing the callback
Live Playground
Best Practices
- Clean up timeouts when component unmounts
- Use refs to store latest callback value
- Keep delay values consistent to prevent unnecessary re-renders
- Consider using useCallback for the input function
Performance
- Prevents excessive function calls
- Minimal memory usage with proper cleanup
- No unnecessary re-renders
- Efficient handling of rapidly changing values