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;
 | |
| 
 |