UNPKG

@kcuf-hook/use-debounced

Version:
78 lines (77 loc) 2.75 kB
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import { useRef, useMemo, useEffect } from 'react'; import useIsUnmounted from '@kcuf-hook/use-is-unmounted'; import { resolveOptions } from '../util'; export default function useDebouncedCallback(fn, options) { var refFn = useRef(fn); var refArgs = useRef(null); // 上次调用 `fn` 的参数列表,执行后会被清空 var refTimeCalled = useRef(0); // 上次调用 `fn` 的时间(但不一定执行) var refTimeInvoked = useRef(0); // 上次真正执行 `fn` 的时间 var refTimerId = useRef(null); var isUnmounted = useIsUnmounted(); var _resolveOptions = resolveOptions(options), delay = _resolveOptions.delay, delayMax = _resolveOptions.delayMax, immediate = _resolveOptions.immediate; refFn.current = fn; // always fresh useEffect(function () { return function () { if (refTimerId.current) { clearTimeout(refTimerId.current); } refTimerId.current = null; }; }, []); return useMemo(function () { function invokeFn() { var args = refArgs.current; if (args) { refArgs.current = null; refTimeInvoked.current = Date.now(); refFn.current.apply(refFn, _toConsumableArray(args)); } } function startTimer(pendingFunc, wait) { if (refTimerId.current) { clearTimeout(refTimerId.current); } refTimerId.current = setTimeout(pendingFunc, wait); } function timerExpired() { if (isUnmounted()) { return; } if (Date.now() - refTimeCalled.current >= delay) { refTimerId.current = null; invokeFn(); return; } var time = Date.now(); var timeSinceLastCall = time - refTimeCalled.current; var timeSinceLastInvoke = time - refTimeInvoked.current; var timeWaiting = delay - timeSinceLastCall; var remainingWait = delayMax >= delay ? Math.min(timeWaiting, delayMax - timeSinceLastInvoke) : timeWaiting; startTimer(timerExpired, remainingWait); } function callFn() { var time = Date.now(); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } refArgs.current = args; refTimeCalled.current = time; if (immediate && !refTimerId.current) { invokeFn(); } if (delayMax >= delay && time - refTimeInvoked.current >= delayMax) { invokeFn(); startTimer(timerExpired, delay); } if (!refTimerId.current) { startTimer(timerExpired, delay); } } return callFn; }, [delay, delayMax, immediate, isUnmounted]); } //# sourceMappingURL=use-debounced-callback.js.map