Skip to content

Commit 176aecf

Browse files
committed
handle useTimer with single seconds state and create util files for Validate and Time
1 parent e47dfc5 commit 176aecf

File tree

4 files changed

+70
-113
lines changed

4 files changed

+70
-113
lines changed

src/useTimer.js

Lines changed: 22 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,57 @@
11
import { useState, useEffect, useRef } from 'react';
2-
3-
4-
function isValidExpiryTimestamp(expiryTimestamp) {
5-
const isValid = (new Date(expiryTimestamp)).getTime() > 0;
6-
if (!isValid) {
7-
console.warn('react-timer-hook: { useTimer } Invalid expiryTimestamp settings', expiryTimestamp);
8-
}
9-
return isValid;
10-
}
11-
12-
function isValidOnExpire(onExpire) {
13-
const isValid = onExpire && typeof onExpire === 'function';
14-
if (onExpire && !isValid) {
15-
console.warn('react-timer-hook: { useTimer } Invalid onExpire settings function', onExpire);
16-
}
17-
return isValid;
18-
}
2+
import { Time, Validate } from './utils';
193

204
export default function useTimer(settings) {
215
const { expiryTimestamp: expiry, onExpire } = settings || {};
226
const [expiryTimestamp, setExpiryTimestamp] = useState(expiry);
23-
24-
const [seconds, setSeconds] = useState(0);
25-
const [minutes, setMinutes] = useState(0);
26-
const [hours, setHours] = useState(0);
27-
const [days, setDays] = useState(0);
7+
const [seconds, setSeconds] = useState(Time.getSecondsFromExpiry(expiryTimestamp));
288
const intervalRef = useRef();
299

30-
function reset() {
10+
function clearIntervalRef() {
3111
if (intervalRef.current) {
3212
clearInterval(intervalRef.current);
3313
intervalRef.current = undefined;
3414
}
35-
setSeconds(0);
36-
setMinutes(0);
37-
setHours(0);
38-
setDays(0);
39-
}
40-
41-
function subtractDay() {
42-
setDays((prevDays) => {
43-
if (prevDays > 0) {
44-
return prevDays - 1;
45-
}
46-
reset();
47-
isValidOnExpire(onExpire) && onExpire();
48-
return 0;
49-
});
50-
}
51-
52-
function subtractHour() {
53-
setHours((prevHours) => {
54-
if (prevHours === 0) {
55-
subtractDay();
56-
return 23;
57-
}
58-
59-
if (prevHours > 0) {
60-
return prevHours - 1;
61-
}
62-
return 0;
63-
});
64-
}
65-
66-
function subtractMinute() {
67-
setMinutes((prevMinutes) => {
68-
if (prevMinutes === 0) {
69-
subtractHour();
70-
return 59;
71-
}
72-
73-
if (prevMinutes > 0) {
74-
return prevMinutes - 1;
75-
}
76-
return 0;
77-
});
78-
}
79-
80-
function subtractSecond() {
81-
setSeconds((prevSeconds) => {
82-
if (prevSeconds === 0) {
83-
subtractMinute();
84-
return 59;
85-
}
86-
87-
if (prevSeconds > 0) {
88-
return prevSeconds - 1;
89-
}
90-
return 0;
91-
});
92-
}
93-
94-
// Timer expiry date calculation
95-
function calculateExpiryDate() {
96-
const now = new Date().getTime();
97-
const distance = expiryTimestamp - now;
98-
const daysValue = Math.floor(distance / (1000 * 60 * 60 * 24));
99-
const hoursValue = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
100-
const minutesValue = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
101-
const secondsValue = Math.floor((distance % (1000 * 60)) / 1000);
102-
if (secondsValue < 0) {
103-
reset();
104-
isValidOnExpire(onExpire) && onExpire();
105-
} else {
106-
setSeconds(secondsValue);
107-
setMinutes(minutesValue);
108-
setHours(hoursValue);
109-
setDays(daysValue);
110-
}
11115
}
11216

11317
function start() {
114-
if (isValidExpiryTimestamp(expiryTimestamp) && !intervalRef.current) {
115-
calculateExpiryDate();
116-
intervalRef.current = setInterval(() => calculateExpiryDate(), 1000);
18+
if (!intervalRef.current) {
19+
intervalRef.current = setInterval(() => {
20+
const secondsValue = Time.getSecondsFromExpiry(expiryTimestamp);
21+
if (secondsValue <= 0) {
22+
clearIntervalRef();
23+
Validate.onExpire(onExpire) && onExpire();
24+
}
25+
setSeconds(secondsValue);
26+
}, 1000);
11727
}
11828
}
11929

12030
function pause() {
121-
if (intervalRef.current) {
122-
clearInterval(intervalRef.current);
123-
intervalRef.current = undefined;
124-
}
31+
clearIntervalRef();
12532
}
12633

12734
function resume() {
128-
if (isValidExpiryTimestamp(expiryTimestamp) && !intervalRef.current) {
129-
intervalRef.current = setInterval(() => subtractSecond(), 1000);
35+
if (!intervalRef.current) {
36+
intervalRef.current = setInterval(() => setSeconds((prevSeconds) => (prevSeconds - 1)), 1000);
13037
}
13138
}
13239

13340
function restart(newExpiryTimestamp) {
134-
reset();
41+
clearIntervalRef();
13542
setExpiryTimestamp(newExpiryTimestamp);
13643
}
13744

138-
// didMount effect
13945
useEffect(() => {
140-
start();
141-
return reset;
46+
if (Validate.expiryTimestamp(expiryTimestamp)) {
47+
setSeconds(Time.getSecondsFromExpiry(expiryTimestamp));
48+
start();
49+
}
50+
return clearIntervalRef;
14251
}, [expiryTimestamp]);
14352

14453

14554
return {
146-
seconds, minutes, hours, days, start, pause, resume, restart,
55+
...Time.getTimeFromSeconds(seconds), start, pause, resume, restart,
14756
};
14857
}

src/utils/Time.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export default class Time {
2+
static getTimeFromSeconds(totalSeconds) {
3+
const days = Math.floor(totalSeconds / (60 * 60 * 24));
4+
const hours = Math.floor((totalSeconds % (60 * 60 * 24)) / (60 * 60));
5+
const minutes = Math.floor((totalSeconds % (60 * 60)) / 60);
6+
const seconds = Math.floor(totalSeconds % 60);
7+
8+
return {
9+
seconds,
10+
minutes,
11+
hours,
12+
days,
13+
};
14+
}
15+
16+
static getSecondsFromExpiry(expiry) {
17+
const now = new Date().getTime();
18+
const milliSecondsDistance = expiry - now;
19+
if (milliSecondsDistance > 0) {
20+
return Math.floor(milliSecondsDistance / 1000);
21+
}
22+
return 0;
23+
}
24+
}

src/utils/Validate.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export default class Validate {
2+
static expiryTimestamp(expiryTimestamp) {
3+
const isValid = (new Date(expiryTimestamp)).getTime() > 0;
4+
if (!isValid) {
5+
console.warn('react-timer-hook: { useTimer } Invalid expiryTimestamp settings', expiryTimestamp); // eslint-disable-line
6+
}
7+
return isValid;
8+
}
9+
10+
static onExpire(onExpire) {
11+
const isValid = onExpire && typeof onExpire === 'function';
12+
if (onExpire && !isValid) {
13+
console.warn('react-timer-hook: { useTimer } Invalid onExpire settings function', onExpire); // eslint-disable-line
14+
}
15+
return isValid;
16+
}
17+
}

src/utils/index.js

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

0 commit comments

Comments
 (0)