Skip to main content

useCountdown

/**
* @param {Object} options
* @param {number} options.countStart
* @param {number} [options.countStop=0]
* @param {number} [options.intervalMs=1000]
* @param {boolean} [options.isIncrement=false]
*/
import {useState, useCallback, useRef, useEffect} from 'react';

export default function useCountdown({
countStart,
countStop = 0,
intervalMs = 1000,
isIncrement = false,
}) {
const [initialCount] = useState(countStart);
const [count, setCount] = useState(initialCount);
const intervalRef = useRef(null);

const stop = useCallback(() => {
if (intervalRef.current !== null) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
}, []);

const start = useCallback(() => {
if (intervalRef.current !== null) return;
intervalRef.current = setInterval(() => {
setCount((prev) => {
const next = isIncrement ? prev + 1 : prev - 1;
// check count stop before reapplying next
const reachStop = isIncrement ? next >= countStop : next <= countStop;
if (reachStop) {
stop();
return countStop;
}
return next;
});
}, intervalMs);
}, [countStop, intervalMs, isIncrement, stop]);

const reset = useCallback(() => {
stop();
// reset to initial count
setCount(initialCount);
}, [initialCount, stop]);

useEffect(() => {
return stop;
}, [stop]);

return {
count,
start,
stop,
reset
};
}