69 lines
1.2 KiB
TypeScript
69 lines
1.2 KiB
TypeScript
import {
|
|
useEffect, useRef
|
|
} from 'react';
|
|
|
|
const DEFAULT_CONFIG = {
|
|
timeout: 0,
|
|
ignoreInitialCall: true
|
|
};
|
|
|
|
export function useDebouncedEffect(
|
|
callback: () => (void | (() => void)),
|
|
config: number | {
|
|
timeout?: number;
|
|
ignoreInitialCall?: boolean;
|
|
},
|
|
deps: any[] = []
|
|
): void {
|
|
let currentConfig;
|
|
|
|
if (typeof config === 'object') {
|
|
currentConfig = {
|
|
...DEFAULT_CONFIG,
|
|
...config
|
|
};
|
|
} else {
|
|
currentConfig = {
|
|
...DEFAULT_CONFIG,
|
|
timeout: config
|
|
};
|
|
}
|
|
const {
|
|
timeout, ignoreInitialCall
|
|
} = currentConfig;
|
|
|
|
const data = useRef<{ firstTime: boolean }>({ firstTime: true });
|
|
|
|
useEffect(() => {
|
|
const { firstTime } = data.current;
|
|
|
|
if (firstTime && ignoreInitialCall) {
|
|
data.current.firstTime = false;
|
|
|
|
return;
|
|
}
|
|
|
|
let clearFunc: (() => void) | undefined;
|
|
|
|
const handler = setTimeout(() => {
|
|
clearFunc = callback() ?? undefined;
|
|
}, timeout);
|
|
|
|
return () => {
|
|
clearTimeout(handler);
|
|
|
|
if (clearFunc && typeof clearFunc === 'function') {
|
|
clearFunc();
|
|
}
|
|
};
|
|
}, [
|
|
callback,
|
|
ignoreInitialCall,
|
|
timeout,
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
...deps
|
|
]);
|
|
}
|
|
|
|
export default useDebouncedEffect;
|