1 | ;
|
2 |
|
3 | exports.__esModule = true;
|
4 | exports.default = void 0;
|
5 | var _react = require("react");
|
6 | var _useCommittedRef = _interopRequireDefault(require("./useCommittedRef"));
|
7 | function _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 |
|
68 | function 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 | }
|
93 | var _default = useInterval;
|
94 | exports.default = _default; |
\ | No newline at end of file |