import { useState, useEffect, useCallback, useRef } from 'react'; /** * useDebounce Hook * * 創建一個防抖版本的函數,在指定延遲後執行 * 如果在延遲期間再次調用,會取消前一次並重新開始計時 * * @param callback 要防抖的函數 * @param delay 延遲時間(毫秒) * @returns 防抖後的函數 */ export const useDebounce = any>( callback: T, delay: number ): T => { const timeoutRef = useRef(null); const debouncedCallback = useCallback( (...args: Parameters) => { // 清除之前的定時器 if (timeoutRef.current) { clearTimeout(timeoutRef.current); } // 設置新的定時器 timeoutRef.current = setTimeout(() => { callback(...args); }, delay); }, [callback, delay] ) as T; // 清理函數,組件卸載時清除定時器 const cancel = useCallback(() => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); timeoutRef.current = null; } }, []); // 為返回的函數添加 cancel 方法 (debouncedCallback as any).cancel = cancel; return debouncedCallback; }; /** * useDebouncedValue Hook * * 創建一個防抖版本的值,只有在值穩定一段時間後才更新 * * @param value 要防抖的值 * @param delay 延遲時間(毫秒) * @returns 防抖後的值 */ export const useDebouncedValue = (value: T, delay: number): T => { const [debouncedValue, setDebouncedValue] = useState(value); const timeoutRef = useRef(null); useEffect(() => { // 清除之前的定時器 if (timeoutRef.current) { clearTimeout(timeoutRef.current); } // 設置新的定時器 timeoutRef.current = setTimeout(() => { setDebouncedValue(value); }, delay); // 清理函數 return () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); } }; }, [value, delay]); return debouncedValue; };