56 lines
1.1 KiB
TypeScript
56 lines
1.1 KiB
TypeScript
import { useEffect, useState } from "preact/hooks";
|
|
|
|
type ThrottleOptions = {
|
|
leading?: boolean;
|
|
trailing?: boolean;
|
|
};
|
|
|
|
const useThrottledCallback = (
|
|
callback: (...args: any[]) => void,
|
|
delay: number,
|
|
options: ThrottleOptions = {},
|
|
) => {
|
|
const { leading = true, trailing = true } = options;
|
|
|
|
const [lastExecTime, setLastExecTime] = useState(0);
|
|
const [timer, setTimer] = useState<number | null>(null);
|
|
const [isLeading, setIsLeading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
return () => {
|
|
if (timer) {
|
|
clearTimeout(timer);
|
|
}
|
|
};
|
|
}, [timer]);
|
|
|
|
const throttledCallback = (...args: any[]) => {
|
|
const now = Date.now();
|
|
|
|
if (leading && !isLeading) {
|
|
callback(...args);
|
|
setLastExecTime(now);
|
|
setIsLeading(true);
|
|
}
|
|
|
|
if (trailing) {
|
|
if (timer) {
|
|
clearTimeout(timer);
|
|
}
|
|
|
|
setTimer(setTimeout(() => {
|
|
if (now - lastExecTime >= delay) {
|
|
callback(...args);
|
|
setLastExecTime(now);
|
|
}
|
|
setIsLeading(false);
|
|
}, delay));
|
|
}
|
|
};
|
|
|
|
return throttledCallback;
|
|
};
|
|
|
|
export default useThrottledCallback;
|
|
|