ahooks
Version:
react hooks library
77 lines (76 loc) • 3.15 kB
JavaScript
import debounce from 'lodash/debounce';
import { useEffect, useMemo, useRef } from 'react';
import useUpdateEffect from '../../../useUpdateEffect';
import { cancelPendingPromise } from '../utils/cancelledError';
const useDebouncePlugin = (fetchInstance, { debounceWait, debounceLeading, debounceTrailing, debounceMaxWait, ready }) => {
const debouncedRef = useRef(undefined);
const pendingRejectRef = useRef(undefined);
const options = useMemo(() => {
const ret = {};
if (debounceLeading !== undefined) {
ret.leading = debounceLeading;
}
if (debounceTrailing !== undefined) {
ret.trailing = debounceTrailing;
}
if (debounceMaxWait !== undefined) {
ret.maxWait = debounceMaxWait;
}
return ret;
}, [debounceLeading, debounceTrailing, debounceMaxWait]);
useEffect(() => {
if (debounceWait) {
const _originRunAsync = fetchInstance.runAsync.bind(fetchInstance);
debouncedRef.current = debounce((callback) => {
callback();
}, debounceWait, options);
// debounce runAsync should be promise
// https://github.com/lodash/lodash/issues/4400#issuecomment-834800398
fetchInstance.runAsync = (...args) => {
if (fetchInstance.options.ready === false) {
return _originRunAsync(...args);
}
cancelPendingPromise(pendingRejectRef);
return new Promise((resolve, reject) => {
var _a;
let callbackInvoked = false;
pendingRejectRef.current = reject;
(_a = debouncedRef.current) === null || _a === void 0 ? void 0 : _a.call(debouncedRef, () => {
callbackInvoked = true;
pendingRejectRef.current = undefined;
_originRunAsync(...args)
.then(resolve)
.catch(reject);
});
if (!callbackInvoked && options.trailing === false) {
cancelPendingPromise(pendingRejectRef);
}
});
};
return () => {
var _a;
(_a = debouncedRef.current) === null || _a === void 0 ? void 0 : _a.cancel();
cancelPendingPromise(pendingRejectRef);
fetchInstance.runAsync = _originRunAsync;
};
}
}, [debounceWait, options, fetchInstance]);
useUpdateEffect(() => {
var _a;
if (ready === false) {
(_a = debouncedRef.current) === null || _a === void 0 ? void 0 : _a.cancel();
cancelPendingPromise(pendingRejectRef);
}
}, [ready]);
if (!debounceWait) {
return {};
}
return {
onCancel: () => {
var _a;
(_a = debouncedRef.current) === null || _a === void 0 ? void 0 : _a.cancel();
cancelPendingPromise(pendingRejectRef);
},
};
};
export default useDebouncePlugin;