useCountdown()
IMPORTANT: The new useCountdown is deprecating the old one on the next major version.
A simple countdown implementation. Support increment and decrement.
NEW VERSION: A simple countdown implementation. Accepts countStop
(new), countStart
(was seconds
), intervalMs
(was interval
) and isIncrement
as keys of the call argument. Support increment and decrement. Will stop when at countStop
.
Related hooks:
The Hook
1// TODO: example and test2import { useCallback } from 'react'34import { useBoolean, useCounter, useInterval } from 'usehooks-ts'56// Old interface IN & OUT7interface UseCountdownType {8 seconds: number9 interval: number10 isIncrement?: boolean11}12interface CountdownHelpers {13 start: () => void14 stop: () => void15 reset: () => void16}1718// New interface IN & OUT19interface CountdownOption {20 countStart: number21 intervalMs?: number22 isIncrement?: boolean23 countStop?: number24}25interface CountdownControllers {26 startCountdown: () => void27 stopCountdown: () => void28 resetCountdown: () => void29}3031/**32 *33 * @param {UseCountdownType} countdownOption34 * @param {number} countdownOption.seconds the countdown's number, generally time seconds35 * @param {number} countdownOption.interval the countdown's interval, milliseconds36 * @param {?boolean} countdownOption.isIncrement false by default, determine the countdown is increment, otherwise is decrement37 * @returns [counter, CountdownControllers]38 *39 * @deprecated new useCountdown interface is already available (see https://usehooks-ts.com/react-hook/use-countdown), the old version will retire on usehooks-ts@340 */41function useCountdown(42 countdownOption: UseCountdownType,43): [number, CountdownHelpers]4445/**46 * New interface with default value47 *48 * @param {CountdownOption} countdownOption49 * @param {number} countdownOption.countStart - the countdown's starting number, initial value of the returned number.50 * @param {?number} countdownOption.countStop - `0` by default, the countdown's stopping number. Pass `-Infinity` to decrease forever.51 * @param {?number} countdownOption.intervalMs - `1000` by default, the countdown's interval, in milliseconds.52 * @param {?boolean} countdownOption.isIncrement - `false` by default, true if the countdown is increment.53 * @returns [counter, CountdownControllers]54 */55function useCountdown(56 countdownOption: CountdownOption,57): [number, CountdownControllers]5859function useCountdown(60 countdownOption: UseCountdownType | CountdownOption,61): [number, CountdownHelpers | CountdownControllers] {62 /**63 * Use to determine the the API call is a deprecated version.64 */65 let isDeprecated = false6667 let countStart,68 intervalMs,69 isIncrement: boolean | undefined,70 countStop: number | undefined7172 if ('seconds' in countdownOption) {73 console.warn(74 '[useCountdown:DEPRECATED] new interface is already available (see https://usehooks-ts.com/react-hook/use-countdown), the old version will retire on usehooks-ts@3.',75 )7677 isDeprecated = true78 countStart = countdownOption.seconds79 intervalMs = countdownOption.interval80 isIncrement = countdownOption.isIncrement81 } else {82 // eslint-disable-next-line @typescript-eslint/no-extra-semi83 ;({ countStart, intervalMs, isIncrement, countStop } = countdownOption)84 }8586 // default values87 intervalMs = intervalMs ?? 100088 isIncrement = isIncrement ?? false89 countStop = countStop ?? 09091 const {92 count,93 increment,94 decrement,95 reset: resetCounter,96 } = useCounter(countStart)9798 /**99 * Note: used to control the useInterval100 * running: If true, the interval is running101 * start: Should set running true to trigger interval102 * stop: Should set running false to remove interval103 */104 const {105 value: isCountdownRunning,106 setTrue: startCountdown,107 setFalse: stopCountdown,108 } = useBoolean(false)109110 /**111 * Will set running false and reset the seconds to initial value112 */113 const resetCountdown = () => {114 stopCountdown()115 resetCounter()116 }117118 const countdownCallback = useCallback(() => {119 if (count === countStop) {120 stopCountdown()121 return122 }123124 if (isIncrement) {125 increment()126 } else {127 decrement()128 }129 }, [count, countStop, decrement, increment, isIncrement, stopCountdown])130131 useInterval(countdownCallback, isCountdownRunning ? intervalMs : null)132133 return isDeprecated134 ? [135 count,136 {137 start: startCountdown,138 stop: stopCountdown,139 reset: resetCountdown,140 } as CountdownHelpers,141 ]142 : [143 count,144 {145 startCountdown,146 stopCountdown,147 resetCountdown,148 } as CountdownControllers,149 ]150}151152export default useCountdown
Usage
1import { ChangeEvent, useState } from 'react'23import { useCountdown } from 'usehooks-ts'45export default function Component() {6 const [intervalValue, setIntervalValue] = useState<number>(1000)7 const [count, { startCountdown, stopCountdown, resetCountdown }] =8 useCountdown({9 countStart: 60,10 intervalMs: intervalValue,11 })1213 const handleChangeIntervalValue = (event: ChangeEvent<HTMLInputElement>) => {14 setIntervalValue(Number(event.target.value))15 }16 return (17 <div>18 <p>Count: {count}</p>1920 <input21 type="number"22 value={intervalValue}23 onChange={handleChangeIntervalValue}24 />25 <button onClick={startCountdown}>start</button>26 <button onClick={stopCountdown}>stop</button>27 <button onClick={resetCountdown}>reset</button>28 </div>29 )30}
See a way to make this page better?
Edit there »