UNPKG

@react-hookz/web

Version:

React hooks done right, for browser and SSR.

74 lines (73 loc) 2.82 kB
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)); }