Skip to content

Commit 24df843

Browse files
committed
add useInterval and reimplement useTimer in cleaner way
1 parent a24d420 commit 24df843

File tree

6 files changed

+163
-67
lines changed

6 files changed

+163
-67
lines changed

demo/components/UseTimerDemo.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ export default function UseTimerDemo({ expiryTimestamp }: Object) {
1313
pause,
1414
resume,
1515
restart,
16-
} = useTimer({ expiryTimestamp, onExpire: () => console.warn('onExpire called') });
17-
16+
} = useTimer({ expiryTimestamp, autoStart: true, onExpire: () => console.warn('onExpire called') });
1817

1918
return (
2019
<div>

docs/index.js

Lines changed: 26 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/hooks/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import useInterval from './useInterval';
2+
3+
export {
4+
useInterval,
5+
};

src/hooks/useInterval.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { useEffect, useRef } from 'react';
2+
3+
export default function useInterval(callback, delay) {
4+
const callbacRef = useRef();
5+
6+
// update callback function with current render callback that has access to latest props and state
7+
useEffect(() => {
8+
callbacRef.current = callback;
9+
});
10+
11+
useEffect(() => {
12+
const interval = setInterval(() => {
13+
callbacRef.current && callbacRef.current();
14+
}, delay);
15+
return () => clearInterval(interval);
16+
}, [delay]);
17+
}

src/useTimer-old.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { useState, useEffect, useRef } from 'react';
2+
import { Time, Validate } from './utils';
3+
4+
export default function useTimer(settings) {
5+
const { expiryTimestamp: expiry, onExpire } = settings || {};
6+
const [expiryTimestamp, setExpiryTimestamp] = useState(expiry);
7+
const [seconds, setSeconds] = useState(Time.getSecondsFromExpiry(expiryTimestamp));
8+
const [isRunning, setIsRunning] = useState(true);
9+
const intervalRef = useRef();
10+
11+
function clearIntervalRef() {
12+
if (intervalRef.current) {
13+
setIsRunning(false);
14+
clearInterval(intervalRef.current);
15+
intervalRef.current = undefined;
16+
}
17+
}
18+
19+
function handleExpire() {
20+
clearIntervalRef();
21+
Validate.onExpire(onExpire) && onExpire();
22+
}
23+
24+
function start() {
25+
if (!intervalRef.current) {
26+
setIsRunning(true);
27+
intervalRef.current = setInterval(() => {
28+
const secondsValue = Time.getSecondsFromExpiry(expiryTimestamp);
29+
if (secondsValue <= 0) {
30+
handleExpire();
31+
}
32+
setSeconds(secondsValue);
33+
}, 1000);
34+
}
35+
}
36+
37+
function pause() {
38+
clearIntervalRef();
39+
}
40+
41+
function resume() {
42+
if (!intervalRef.current) {
43+
setIsRunning(true);
44+
intervalRef.current = setInterval(() => setSeconds((prevSeconds) => {
45+
const secondsValue = prevSeconds - 1;
46+
if (secondsValue <= 0) {
47+
handleExpire();
48+
}
49+
return secondsValue;
50+
}), 1000);
51+
}
52+
}
53+
54+
function restart(newExpiryTimestamp) {
55+
clearIntervalRef();
56+
setExpiryTimestamp(newExpiryTimestamp);
57+
}
58+
59+
function handleExtraMilliSeconds(secondsValue, extraMilliSeconds) {
60+
setIsRunning(true);
61+
intervalRef.current = setTimeout(() => {
62+
const currentSeconds = Time.getSecondsFromExpiry(expiryTimestamp);
63+
setSeconds(currentSeconds);
64+
if (currentSeconds <= 0) {
65+
handleExpire();
66+
} else {
67+
intervalRef.current = undefined;
68+
start();
69+
}
70+
}, extraMilliSeconds);
71+
}
72+
73+
useEffect(() => {
74+
if (Validate.expiryTimestamp(expiryTimestamp)) {
75+
const secondsValue = Time.getSecondsFromExpiry(expiryTimestamp);
76+
const extraMilliSeconds = Math.floor((secondsValue - Math.floor(secondsValue)) * 1000);
77+
setSeconds(secondsValue);
78+
if (extraMilliSeconds > 0) {
79+
handleExtraMilliSeconds(secondsValue, extraMilliSeconds);
80+
} else {
81+
start();
82+
}
83+
}
84+
return clearIntervalRef;
85+
}, [expiryTimestamp]);
86+
87+
88+
return {
89+
...Time.getTimeFromSeconds(seconds), start, pause, resume, restart, isRunning,
90+
};
91+
}

0 commit comments

Comments
 (0)