@rooks/use-countdown
Version:
Count down to a target timestamp and call callbacks every second (or provided peried)
88 lines (84 loc) • 2.72 kB
JavaScript
import { useRef, useState, useEffect } from 'react';
// See also: https://overreacted.io/making-setinterval-declarative-with-react-hooks/
/**
*
* useInterval hook
*
* Declaratively creates a setInterval to run a callback after a fixed
* amount of time
*
*@param {funnction} callback - Callback to be fired
*@param {number} intervalId - Interval duration in milliseconds after which the callback is to be fired
*@param {boolean} startImmediate - Whether the interval should start immediately on initialise
*@return {IntervalHandler}
*/
function useInterval(callback, intervalDuration, startImmediate = false) {
const internalIdRef = useRef(null);
const [isRunning, setIsRunning] = useState(startImmediate);
const savedCallback = useRef();
function start() {
if (!isRunning) {
setIsRunning(true);
}
}
function stop() {
if (isRunning) {
setIsRunning(false);
}
}
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
});
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current && savedCallback.current();
}
if (intervalDuration !== null && isRunning) {
let id = setInterval(tick, intervalDuration);
internalIdRef.current = id;
return () => {
internalIdRef.current = null;
clearInterval(id);
};
}
}, [intervalDuration, isRunning]);
let handler;
handler = [start, stop, internalIdRef.current];
handler.start = start;
handler.stop = stop;
handler.intervalId = internalIdRef.current;
return handler;
}
/**
*
* useCountdown
* Easy way to countdown until a given endtime in intervals
* @param endTime Time to countdown
* @param options Countdown options
*/
function useCountdown(endTime, options = {}) {
const { interval = 1000, onDown, onEnd } = options;
const [time, setTime] = useState(() => new Date());
const restTime = endTime.getTime() - time.getTime();
const count = restTime > 0 ? Math.ceil(restTime / interval) : 0;
useInterval(onTick, count ? interval : null, true);
return count;
function onTick() {
const newTime = new Date();
if (newTime > endTime) {
if (onEnd) {
onEnd(newTime);
}
setTime(endTime);
return;
}
if (onDown) {
onDown(restTime, newTime);
}
setTime(newTime);
}
}
export default useCountdown;
//# sourceMappingURL=index.esm.js.map