Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | 5x 5x 5x 5x 5x 5x 5x 5x 14x 9x 14x 5x 5x | /**
* useDebounce Hook
*
* Debounces a function to execute only after a delay since the last call.
* Useful for search inputs, resize handlers, and other delayed actions.
*
* Uses a ref pattern to ensure the latest callback is always called
* without recreating the debounced function on every render.
*
* @module hooks/useDebounce
* @category Performance
* @korean 디바운스 훅
*/
import { useCallback, useRef, useLayoutEffect, useEffect } from 'react';
/**
* Hook to debounce a callback function
*
* @param callback - Function to debounce
* @param delay - Delay in milliseconds before execution
* @returns Debounced function
*
* @example
* ```tsx
* const handleSearch = useDebounce((query: string) => {
* // Perform search
* }, 300);
* ```
*/
export function useDebounce<T extends (...args: unknown[]) => void>(
callback: T,
delay: number
): (...args: Parameters<T>) => void {
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
const callbackRef = useRef(callback);
// Keep callback ref up to date
useLayoutEffect(() => {
callbackRef.current = callback;
});
// Cleanup on unmount
useEffect(() => {
return () => {
Iif (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, []);
return useCallback(
(...args: Parameters<T>) => {
// Clear existing timeout
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
// Set new timeout
timeoutRef.current = setTimeout(() => {
callbackRef.current(...args);
timeoutRef.current = null;
}, delay);
},
[delay]
);
}
export default useDebounce;
|