UNPKG

@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
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