React hook to create a timer functionality.
Add the hook via the CLI:
npx @novajslabs/cli add useTimer
Or copy and paste the code into your project:
import { useState, useEffect } from 'react'
const parseTime = (time: string) => {
const splitTime = time.split(':')
const [days, hours, minutes, seconds] = splitTime.map((value) =>
Number(value),
)
return { days, hours, minutes, seconds }
}
const addLeadingZero = (digit: number): string => {
let timeStr = ''
digit % 10 === digit ? (timeStr += `0${digit}`) : (timeStr += `${digit}`)
return timeStr
}
interface Timer {
current: string
isPaused: boolean
isOver: boolean
currentDays: number
currentHours: number
currentMinutes: number
currentSeconds: number
elapsedSeconds: number
remainingSeconds: number
pause: () => void
play: () => void
reset: () => void
togglePause: () => void
}
export const useTimer = (startTime: string): Timer => {
const { days, hours, minutes, seconds } = parseTime(startTime)
const [time, setTime] = useState({ days, hours, minutes, seconds })
const [paused, setPaused] = useState(false)
const divider = ':'
const [isOver, setIsOver] = useState(false)
useEffect(() => {
if (paused) {
return
}
const interval = setInterval(() => {
setTime((prev) => {
let d = prev.days
let h = prev.hours
let m = prev.minutes
let s = prev.seconds
if (s - 1 < 0) {
s = 59
if (m - 1 < 0) {
m = 59
if (h - 1 < 0) {
h = 23
if (d - 1 >= 0) {
d--
}
} else {
h--
}
} else {
m--
}
} else {
s--
}
return { days: d, hours: h, minutes: m, seconds: s }
})
}, 1000)
if (
time.seconds === 0 &&
time.minutes === 0 &&
time.hours === 0 &&
time.days === 0
) {
setIsOver(true)
clearInterval(interval)
return
}
return () => clearInterval(interval)
}, [days, hours, minutes, seconds, time, paused])
return {
current: `${addLeadingZero(time.days)}${divider}${addLeadingZero(
time.hours,
)}${divider}${addLeadingZero(time.minutes)}${divider}${addLeadingZero(
time.seconds,
)}`,
isPaused: paused,
isOver,
currentDays: time.days,
currentHours: time.hours,
currentMinutes: time.minutes,
currentSeconds: time.seconds,
elapsedSeconds:
days * 86400 +
hours * 3600 +
minutes * 60 +
seconds -
(time.days * 86400 +
time.hours * 3600 +
time.minutes * 60 +
time.seconds),
remainingSeconds:
time.days * 86400 + time.hours * 3600 + time.minutes * 60 + time.seconds,
pause: () => setPaused(true),
play: () => setPaused(false),
reset: () => {
setIsOver(false)
setTime({ days, hours, minutes, seconds })
},
togglePause: () => {
setPaused(!paused)
},
}
}
React 16.8 or higher
- Name
startTime
- Type
- string
- Required
- required
- Description
Represents the initial value of the timer in the format dd:hh:mm:ss.
- Name
current
- Type
- string
- Description
The current value of the timer.
- Name
isPaused
- Type
- boolean
- Description
Represents whether the timer is paused (true) or not (false).
- Name
isOver
- Type
- boolean
- Description
Represents whether the timer has ended (true) or not (false).
- Name
currentDays
- Type
- number
- Description
The current value of days on the timer.
- Name
currentHours
- Type
- number
- Description
The current value of hours on the timer.
- Name
currentMinutes
- Type
- number
- Description
The current value of minutes on the timer.
- Name
currentSeconds
- Type
- number
- Description
The current value of the seconds in the timer.
- Name
elapsedSeconds
- Type
- number
- Description
The number of seconds that have passed since the start of the timer.
- Name
remainingSeconds
- Type
- number
- Description
The number of seconds left until the stopwatch ends.
- Name
pause
- Type
- function
- Description
Pause the timer.
- Name
play
- Type
- function
- Description
Play the timer.
- Name
reset
- Type
- function
- Description
Reset the timer.
- Name
togglePause
- Type
- function
- Description
Toggle between pausing and playing the timer.
import { useTimer } from './hooks/useTimer'
const App = () => {
const {
current,
isPaused,
isOver,
currentDays,
currentHours,
currentMinutes,
currentSeconds,
elapsedSeconds,
remainingSeconds,
pause,
play,
reset,
togglePause,
} = useTimer('00:00:00:05')
return (
<div>
<p>Counter value: {current}</p>
<p>Is the counter paused? {isPaused ? 'Yes' : 'No'}</p>
<p>Has the counter over? {isOver ? 'Yes' : 'No'}</p>
<p>Current days: {currentDays}</p>
<p>Current hours: {currentHours}</p>
<p>Current minutes: {currentMinutes}</p>
<p>Current seconds: {currentSeconds}</p>
<p>Elapsed seconds: {elapsedSeconds}</p>
<p>Remaining seconds: {remainingSeconds}</p>
<button onClick={pause}>Pause</button>
<button onClick={play}>Play</button>
<button onClick={reset}>Reset</button>
<button onClick={togglePause}>Toggle Pause</button>
</div>
)
}
export default App
Here are some use cases where this React hook is useful:
- Implementing a countdown timer for a time-limited quiz or exam in an online learning platform
- Creating a countdown clock for tracking time-sensitive tasks or deadlines in a project management tool
- Developing a timer feature for timing cooking recipes or workouts in a fitness app
- Adding a countdown timer for promotions or special events in an e-commerce website
- Integrating a timer functionality for time-bound challenges or activities in a gamified learning platform