42 lines
1.0 KiB
TypeScript
42 lines
1.0 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useMemo, useRef } from "react";
|
|
|
|
type Procedure<T extends unknown[]> = (...args: T) => void;
|
|
type DebouncedProcedure<T extends unknown[]> = Procedure<T> & { cancel: () => void };
|
|
|
|
/**
|
|
* 用于本地输入的防抖工具,默认等待 800ms 再触发回调。
|
|
*/
|
|
export const useDebouncedCallback = <T extends unknown[]>(
|
|
callback: Procedure<T>,
|
|
delay: number,
|
|
): DebouncedProcedure<T> => {
|
|
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
const callbackRef = useRef(callback);
|
|
|
|
useEffect(() => {
|
|
callbackRef.current = callback;
|
|
}, [callback]);
|
|
|
|
return useMemo(() => {
|
|
const debounced = ((...args: T) => {
|
|
if (timerRef.current) {
|
|
clearTimeout(timerRef.current);
|
|
}
|
|
timerRef.current = setTimeout(() => {
|
|
callbackRef.current(...args);
|
|
}, delay);
|
|
}) as DebouncedProcedure<T>;
|
|
|
|
debounced.cancel = () => {
|
|
if (timerRef.current) {
|
|
clearTimeout(timerRef.current);
|
|
timerRef.current = null;
|
|
}
|
|
};
|
|
|
|
return debounced;
|
|
}, [delay]);
|
|
};
|