UNPKG

@conodene/usetimeout-react-hook

Version:

React.js custom hook that sets a leak-safe timeout and returns a function to cancel it before the timeout expires.

89 lines (82 loc) 4.16 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var react = require('react'); /** * useTimeout is a React.js custom hook that sets a leak-safe timeout and returns * a function to cancel it before the timeout expires. * It's composed of two other native hooks, useRef and useEffect. * It requires a custom way of setting a timeout and clearing it, expressed as an implementation * of the generic TimeoutHandler<T> interface. * The timer is restarted every time an item in `deps` changes. * If a new callback is given to the hook before the previous timeout expires, * only the new callback will be executed at the moment the timeout expires. * When the hook receives a new callback, the timeout isn't reset. * * @param callback the function to be executed after the timeout expires * @param timeout the number of milliseconds after which the callback should be triggered * @param timeHandler TimeoutHandler instance that's used to set and clear the timeout * @param deps useEffect dependencies that should cause the timeout to be reset * @return function to cancel the timer before the timeout expires */ var useTimeout = function (callback, timeout, timeHandler, deps) { if (deps === void 0) { deps = []; } var refCallback = react.useRef(); var refTimer = react.useRef(); react.useEffect(function () { refCallback.current = callback; }, [callback]); /** * The timer is restarted every time an item in `deps` changes. * * TODO: The `react-hooks/exhaustive-deps` ESLint warning is disabled due to the fact that * the linter isn't able to detect misused `useEffect` dependencies when given a computed * array (such as `deps`). If possible, another solution that doesn't block the linter * should be used. */ react.useEffect(function () { var timerID = timeHandler.setTimeout(refCallback.current, timeout); refTimer.current = timerID; // cleans the timer identified by timerID when the effect is unmounted. return function () { return timeHandler.clearTimeout(timerID); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, deps); /** * Returns a function that can be used to cancel the current timeout. * It does so using `timeHandler.clearTimeout` without exposing the last * reference to the timer to the user. */ function cancelTimer() { return timeHandler.clearTimeout(refTimer.current); } return cancelTimer; }; /** * defaultTimeoutHandler implements the TimeoutHandler interface with the usual timer * functions available in browsers and in React Native, i.e. `setTimeout` and `clearTimeout`. */ var defaultTimeoutHandler = { setTimeout: function (fn, timeout) { return window.setTimeout(fn, timeout); }, clearTimeout: function (timeout) { window.clearTimeout(timeout); }, }; /** * useTimeoutDefault is a React.js custom hook that sets a leak-safe timeout and returns * a function to cancel it before the timeout expires. * It uses the default timeout handlers, i.e. window.setTimeout and window.clearTimeout. * It's composed of two other native hooks, useRef and useEffect. * If a new callback is given to the hook before the previous timeout expires, * only the new callback will be executed at the moment the timeout expires. * When the hook receives a new callback, the timeout isn't reset. * * @param callback the function to be executed after the timeout expires * @param timeout the number of milliseconds after which the callback should be triggered * @param deps useEffect dependencies that should cause the timeout to be reset * @return function to cancel the timer before the timeout expires */ var useTimeoutDefault = function (callback, timeout, deps) { if (deps === void 0) { deps = []; } return (useTimeout(callback, timeout, defaultTimeoutHandler, deps)); }; exports.default = useTimeoutDefault; exports.defaultTimeoutHandler = defaultTimeoutHandler; exports.useTimeout = useTimeout; //# sourceMappingURL=index.js.map