UNPKG

2.78 kBJavaScriptView Raw
1"use strict";
2
3exports.__esModule = true;
4exports.default = void 0;
5var _react = require("react");
6var _useCommittedRef = _interopRequireDefault(require("./useCommittedRef"));
7function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
8/**
9 * Creates a `setInterval` that is properly cleaned up when a component unmounted
10 *
11 * ```tsx
12 * function Timer() {
13 * const [timer, setTimer] = useState(0)
14 * useInterval(() => setTimer(i => i + 1), 1000)
15 *
16 * return <span>{timer} seconds past</span>
17 * }
18 * ```
19 *
20 * @param fn an function run on each interval
21 * @param ms The milliseconds duration of the interval
22 */
23
24/**
25 * Creates a pausable `setInterval` that is properly cleaned up when a component unmounted
26 *
27 * ```tsx
28 * const [paused, setPaused] = useState(false)
29 * const [timer, setTimer] = useState(0)
30 *
31 * useInterval(() => setTimer(i => i + 1), 1000, paused)
32 *
33 * return (
34 * <span>
35 * {timer} seconds past
36 *
37 * <button onClick={() => setPaused(p => !p)}>{paused ? 'Play' : 'Pause' }</button>
38 * </span>
39 * )
40 * ```
41 *
42 * @param fn an function run on each interval
43 * @param ms The milliseconds duration of the interval
44 * @param paused Whether or not the interval is currently running
45 */
46
47/**
48 * Creates a pausable `setInterval` that _fires_ immediately and is
49 * properly cleaned up when a component unmounted
50 *
51 * ```tsx
52 * const [timer, setTimer] = useState(-1)
53 * useInterval(() => setTimer(i => i + 1), 1000, false, true)
54 *
55 * // will update to 0 on the first effect
56 * return <span>{timer} seconds past</span>
57 * ```
58 *
59 * @param fn an function run on each interval
60 * @param ms The milliseconds duration of the interval
61 * @param paused Whether or not the interval is currently running
62 * @param runImmediately Whether to run the function immediately on mount or unpause
63 * rather than waiting for the first interval to elapse
64 *
65
66 */
67
68function useInterval(fn, ms, paused = false, runImmediately = false) {
69 let handle;
70 const fnRef = (0, _useCommittedRef.default)(fn);
71 // this ref is necessary b/c useEffect will sometimes miss a paused toggle
72 // orphaning a setTimeout chain in the aether, so relying on it's refresh logic is not reliable.
73 const pausedRef = (0, _useCommittedRef.default)(paused);
74 const tick = () => {
75 if (pausedRef.current) return;
76 fnRef.current();
77 schedule(); // eslint-disable-line no-use-before-define
78 };
79
80 const schedule = () => {
81 clearTimeout(handle);
82 handle = setTimeout(tick, ms);
83 };
84 (0, _react.useEffect)(() => {
85 if (runImmediately) {
86 tick();
87 } else {
88 schedule();
89 }
90 return () => clearTimeout(handle);
91 }, [paused, runImmediately]);
92}
93var _default = useInterval;
94exports.default = _default;
\No newline at end of file