@react-hookz/web
Version:
React hooks done right, for browser and SSR.
74 lines (73 loc) • 2.82 kB
JavaScript
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useMemo, useRef } from 'react';
import { useUnmountEffect } from "../useUnmountEffect/useUnmountEffect.js";
/**
* Makes passed function debounced, otherwise acts like `useCallback`.
*
* @param callback Function that will be debounced.
* @param deps Dependencies list when to update callback.
* @param delay Debounce delay.
* @param maxWait The maximum time `callback` is allowed to be delayed before
* it's invoked. 0 means no max wait.
*/
export function useDebouncedCallback(callback, deps, delay, maxWait) {
if (maxWait === void 0) { maxWait = 0; }
var timeout = useRef();
var waitTimeout = useRef();
var lastCall = useRef();
var clear = function () {
if (timeout.current) {
clearTimeout(timeout.current);
timeout.current = undefined;
}
if (waitTimeout.current) {
clearTimeout(waitTimeout.current);
waitTimeout.current = undefined;
}
};
// cancel scheduled execution on unmount
useUnmountEffect(clear);
return useMemo(function () {
var execute = function () {
// barely possible to test this line
/* istanbul ignore next */
if (!lastCall.current)
return;
var context = lastCall.current;
lastCall.current = undefined;
callback.apply(context.this, context.args);
clear();
};
// eslint-disable-next-line func-names
var wrapped = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (timeout.current) {
clearTimeout(timeout.current);
}
lastCall.current = { args: args, this: this };
// plan regular execution
timeout.current = setTimeout(execute, delay);
// plan maxWait execution if required
if (maxWait > 0 && !waitTimeout.current) {
waitTimeout.current = setTimeout(execute, maxWait);
}
};
Object.defineProperties(wrapped, {
length: { value: callback.length },
name: { value: "".concat(callback.name || 'anonymous', "__debounced__").concat(delay) },
});
return wrapped;
}, __spreadArray([delay, maxWait], deps, true));
}