JAVASCRIPT
Throttling Function Calls with `useThrottledCallback`
Create a custom React hook to throttle function calls, ensuring a callback fires at most once within a specified time window, preventing excessive re-renders.
import { useRef, useCallback, useEffect } from 'react';
export const useThrottledCallback = (callback, delay, dependencies = []) => {
const timeoutRef = useRef(null);
const lastArgsRef = useRef(null);
const lastThisRef = useRef(null);
const lastExecTimeRef = useRef(0);
const throttledCallback = useCallback(function(...args) {
lastArgsRef.current = args;
lastThisRef.current = this;
const now = Date.now();
const remaining = delay - (now - lastExecTimeRef.current);
if (remaining <= 0 || remaining > delay) {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
lastExecTimeRef.current = now;
callback.apply(this, args);
} else if (!timeoutRef.current) {
timeoutRef.current = setTimeout(() => {
lastExecTimeRef.current = Date.now();
timeoutRef.current = null;
callback.apply(lastThisRef.current, lastArgsRef.current);
lastArgsRef.current = null;
lastThisRef.current = null;
}, remaining);
}
}, [callback, delay, ...dependencies]);
useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, [delay]);
return throttledCallback;
};
How it works: This `useThrottledCallback` hook limits the rate at which a function can execute. It ensures the `callback` is called at most once within the specified `delay` period. Useful for performance-critical events like window resizing or scrolling, it prevents rapid, unnecessary updates by queuing subsequent calls until the delay has passed. The hook uses `useRef` to maintain mutable values across re-renders and `useCallback` to memoize the throttled function.