@rooks/use-countdown
Version:
Count down to a target timestamp and call callbacks every second (or provided peried)
94 lines (89 loc) • 3.25 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) :
typeof define === 'function' && define.amd ? define(['react'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.useCountdown = factory(global.React));
}(this, (function (react) { 'use strict';
// 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 = react.useRef(null);
const [isRunning, setIsRunning] = react.useState(startImmediate);
const savedCallback = react.useRef();
function start() {
if (!isRunning) {
setIsRunning(true);
}
}
function stop() {
if (isRunning) {
setIsRunning(false);
}
}
// Remember the latest callback.
react.useEffect(() => {
savedCallback.current = callback;
});
// Set up the interval.
react.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] = react.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);
}
}
return useCountdown;
})));
//# sourceMappingURL=index.js.map