UNPKG

2.37 kBJavaScriptView Raw
1"use strict";
2
3exports.__esModule = true;
4exports.default = useTimeout;
5
6var _react = require("react");
7
8var _useMounted = _interopRequireDefault(require("./useMounted"));
9
10var _useWillUnmount = _interopRequireDefault(require("./useWillUnmount"));
11
12function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14/*
15 * Browsers including Internet Explorer, Chrome, Safari, and Firefox store the
16 * delay as a 32-bit signed integer internally. This causes an integer overflow
17 * when using delays larger than 2,147,483,647 ms (about 24.8 days),
18 * resulting in the timeout being executed immediately.
19 *
20 * via: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
21 */
22var MAX_DELAY_MS = Math.pow(2, 31) - 1;
23
24function setChainedTimeout(handleRef, fn, timeoutAtMs) {
25 var delayMs = timeoutAtMs - Date.now();
26 handleRef.current = delayMs <= MAX_DELAY_MS ? setTimeout(fn, delayMs) : setTimeout(function () {
27 return setChainedTimeout(handleRef, fn, timeoutAtMs);
28 }, MAX_DELAY_MS);
29}
30/**
31 * Returns a controller object for setting a timeout that is properly cleaned up
32 * once the component unmounts. New timeouts cancel and replace existing ones.
33 *
34 *
35 *
36 * ```tsx
37 * const { set, clear } = useTimeout();
38 * const [hello, showHello] = useState(false);
39 * //Display hello after 5 seconds
40 * set(() => showHello(true), 5000);
41 * return (
42 * <div className="App">
43 * {hello ? <h3>Hello</h3> : null}
44 * </div>
45 * );
46 * ```
47 */
48
49
50function useTimeout() {
51 var isMounted = (0, _useMounted.default)(); // types are confused between node and web here IDK
52
53 var handleRef = (0, _react.useRef)();
54 (0, _useWillUnmount.default)(function () {
55 return clearTimeout(handleRef.current);
56 });
57 return (0, _react.useMemo)(function () {
58 var clear = function clear() {
59 return clearTimeout(handleRef.current);
60 };
61
62 function set(fn, delayMs) {
63 if (delayMs === void 0) {
64 delayMs = 0;
65 }
66
67 if (!isMounted()) return;
68 clear();
69
70 if (delayMs <= MAX_DELAY_MS) {
71 // For simplicity, if the timeout is short, just set a normal timeout.
72 handleRef.current = setTimeout(fn, delayMs);
73 } else {
74 setChainedTimeout(handleRef, fn, Date.now() + delayMs);
75 }
76 }
77
78 return {
79 set: set,
80 clear: clear
81 };
82 }, []);
83}
\No newline at end of file