UNPKG

1.41 kBJavaScriptView Raw
1import { useEffect } from 'react';
2import useCommittedRef from './useCommittedRef';
3/**
4 * Creates a `setInterval` that is properly cleaned up when a component unmounted
5 *
6 * ```tsx
7 * function Timer() {
8 * const [timer, setTimer] = useState(0)
9 * useInterval(() => setTimer(i => i + 1), 1000)
10 *
11 * return <span>{timer} seconds past</span>
12 * }
13 * ```
14 *
15 * @param fn an function run on each interval
16 * @param ms The milliseconds duration of the interval
17 */
18
19function useInterval(fn, ms, paused, runImmediately) {
20 if (paused === void 0) {
21 paused = false;
22 }
23
24 if (runImmediately === void 0) {
25 runImmediately = false;
26 }
27
28 var handle;
29 var fnRef = useCommittedRef(fn); // this ref is necessary b/c useEffect will sometimes miss a paused toggle
30 // orphaning a setTimeout chain in the aether, so relying on it's refresh logic is not reliable.
31
32 var pausedRef = useCommittedRef(paused);
33
34 var tick = function tick() {
35 if (pausedRef.current) return;
36 fnRef.current();
37 schedule(); // eslint-disable-line no-use-before-define
38 };
39
40 var schedule = function schedule() {
41 clearTimeout(handle);
42 handle = setTimeout(tick, ms);
43 };
44
45 useEffect(function () {
46 if (runImmediately) {
47 tick();
48 } else {
49 schedule();
50 }
51
52 return function () {
53 return clearTimeout(handle);
54 };
55 }, [paused, runImmediately]);
56}
57
58export default useInterval;
\No newline at end of file