Files
bodyshop/client/src/utils/countdownHook.js

85 lines
2.4 KiB
JavaScript

import React from "react";
const useCountDown = (timeToCount = 60 * 1000, interval = 1000) => {
const [timeLeft, setTimeLeft] = React.useState(0);
const timer = React.useRef({});
const run = (ts) => {
if (!timer.current.started) {
timer.current.started = ts;
timer.current.lastInterval = ts;
}
const localInterval = Math.min(interval, timer.current.timeLeft || Infinity);
if (ts - timer.current.lastInterval >= localInterval) {
timer.current.lastInterval += localInterval;
setTimeLeft((timeLeft) => {
timer.current.timeLeft = timeLeft - localInterval;
return timer.current.timeLeft;
});
}
if (ts - timer.current.started < timer.current.timeToCount) {
timer.current.requestId = window.requestAnimationFrame(run);
} else {
timer.current = {};
setTimeLeft(0);
}
};
const start = React.useCallback(
(ttc) => {
window.cancelAnimationFrame(timer.current.requestId);
const newTimeToCount = ttc !== undefined ? ttc : timeToCount;
timer.current.started = null;
timer.current.lastInterval = null;
timer.current.timeToCount = newTimeToCount;
timer.current.requestId = window.requestAnimationFrame(run);
setTimeLeft(newTimeToCount);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
const pause = React.useCallback(() => {
window.cancelAnimationFrame(timer.current.requestId);
timer.current.started = null;
timer.current.lastInterval = null;
timer.current.timeToCount = timer.current.timeLeft;
}, []);
const resume = React.useCallback(
() => {
if (!timer.current.started && timer.current.timeLeft > 0) {
window.cancelAnimationFrame(timer.current.requestId);
timer.current.requestId = window.requestAnimationFrame(run);
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
const reset = React.useCallback(() => {
if (timer.current.timeLeft) {
window.cancelAnimationFrame(timer.current.requestId);
timer.current = {};
setTimeLeft(0);
}
}, []);
const actions = React.useMemo(
() => ({ start, pause, resume, reset }), // eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
React.useEffect(() => {
return () => window.cancelAnimationFrame(timer.current.requestId);
}, []);
return [timeLeft, actions];
};
export default useCountDown;