useThrottledCallback Hook
A custom React Hook for throttling functions/callbacks with TypeScript support
Code
import { useCallback, useRef } from 'react';
function useThrottledCallback<T __TOKEN_17__ (...args: any[]) => any>(
callback: T,
delay = 500,
leading = true,
trailing = true
): T {
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
const lastExecRef = useRef<number>(0);
const callbackRef = useRef(callback);
const argsRef = useRef<Parameters<T>>([]);
// Update callback ref on each render
callbackRef.current = callback;
const throttledCallback = useCallback((...args: Parameters<T>) => {
argsRef.current = args;
const now = Date.now();
const elapsed = now - lastExecRef.current;
const execute = () => {
lastExecRef.current = now;
callbackRef.current(...argsRef.current);
};
// Leading execution
__TOKEN_26__ (leading && elapsed >= delay) {
execute();
}
// Trailing execution
else __TOKEN_28__ (trailing && !timeoutRef.current) {
timeoutRef.current = setTimeout(() => {
execute();
timeoutRef.current = null;
}, delay - elapsed);
}
}, [delay, leading, trailing]) as T;
// Cancel throttle
const cancel = useCallback(() => {
__TOKEN_30__ (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
}, []);
__TOKEN_4__
(throttledCallback as any).cancel = cancel;
return throttledCallback;
}
// Usage example
// const handleScroll = useThrottledCallback(() => {
// console.log('Scroll position:', window.scrollY);
// }, 200);
// useEffect(() => {
// window.addEventListener('scroll', handleScroll, { passive: true });
// return () => window.removeEventListener('scroll', handleScroll);
// }, [handleScroll]);