UNPKG

react-better-countdown-hook

Version:

A dead simple react countdown hook with typescript support

103 lines (90 loc) 3.03 kB
import React, { useEffect } from "react" /** Return possible actions */ type CountDownActions = { start: () => void; pause: () => void; reset: () => void; } /** Countdown values to update and return, used as the initial state */ type CountdownValues = { milliseconds: number; seconds: number; minutes: number; hours: number; days: number; } /** Input type */ type CountDownInput = { /** Start time in milliseconds */ startTimeMilliseconds: number; /** interval */ interval: number, /** Optional callback when the countdown reaches 0 */ onCountDownEnd?: () => any } const useCountDown = ({startTimeMilliseconds,interval, onCountDownEnd}: CountDownInput): [CountdownValues, CountDownActions] => { const [timeLeftState, setTimeLeftState] = React.useState<CountdownValues>({ milliseconds: startTimeMilliseconds, seconds: Math.floor(startTimeMilliseconds / 1000), minutes: Math.floor(startTimeMilliseconds / (60 * 1000)), hours: Math.floor(startTimeMilliseconds / (60 * 60 * 1000)), days: Math.floor(startTimeMilliseconds / (24 * 60 * 60 * 1000)), }) const [timerRunning, setTimerRunning] = React.useState<boolean>(false) const start = (): void => { if(timeLeftState.milliseconds > 0 && !timerRunning){ setTimerRunning(true); } } const pause = (): void => { setTimerRunning(false); } const reset = async (): Promise<void> => { setTimerRunning(false); setTimeLeftState({ milliseconds: startTimeMilliseconds, seconds: Math.floor(startTimeMilliseconds / 1000), minutes: Math.floor(startTimeMilliseconds / (60 * 1000)), hours: Math.floor(startTimeMilliseconds / (60 * 60 * 1000)), days: Math.floor(startTimeMilliseconds / (24 * 60 * 60 * 1000)), }); } const countdown = () : NodeJS.Timeout => { return setTimeout(() => (setTimeLeftState({ milliseconds: timeLeftState.milliseconds - interval, seconds: (timeLeftState.milliseconds - interval) / 1000 > 0 ? Math.round((timeLeftState.milliseconds - interval) / 1000): 0, minutes: Math.round((timeLeftState.milliseconds - interval) / (60 * 1000)), hours: Math.round((timeLeftState.milliseconds - interval) / (60 * 60 * 1000)), days: Math.round((timeLeftState.milliseconds - interval) / (24 * 60 * 60 * 1000)), })), interval); } useEffect(() => { let clear : null | NodeJS.Timeout = null; if(timerRunning){ clear = countdown(); } return () => { clearTimeout(clear); } },[timeLeftState, timerRunning]) useEffect((): void => { if(timeLeftState.milliseconds <= 0){ if(onCountDownEnd !== undefined){ onCountDownEnd() } pause() } }, [timeLeftState]) return [{ milliseconds: timeLeftState.milliseconds, seconds: timeLeftState.seconds, minutes: timeLeftState.minutes, hours: timeLeftState.hours, days: timeLeftState.days, },{ start: start, pause: pause, reset: reset, }] } export default useCountDown;