useCountdown
React hook that manages countdown functionality with configurable intervals, increment/decrement modes, and start/stop/reset controls.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/use-countdown.json
npx shadcn@latest add https://www.shadcn.io/registry/use-countdown.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/use-countdown.json
bunx shadcn@latest add https://www.shadcn.io/registry/use-countdown.json
Features
- Flexible direction - Count down or count up with
isIncrement
option - Configurable interval - Set custom intervals in milliseconds
- Auto-stop - Automatically stops when reaching the target value
- Full control - Start, stop, and reset functionality
- Custom boundaries - Set custom start and stop values
- Performance optimized - Uses efficient interval management
Usage
import { useCountdown } from "@/hooks/use-countdown"
function Timer() {
const [count, { startCountdown, stopCountdown, resetCountdown }] = useCountdown({
countStart: 60,
intervalMs: 1000,
})
return (
<div>
<div>Time: {count}</div>
<button onClick={startCountdown}>Start</button>
<button onClick={stopCountdown}>Stop</button>
<button onClick={resetCountdown}>Reset</button>
</div>
)
}
API Reference
useCountdown
useCountdown(options: CountdownOptions): [number, CountdownControllers]
CountdownOptions
Property | Type | Default | Description |
---|---|---|---|
countStart | number | - | Starting number for the countdown (required) |
countStop | number | 0 | Stopping number (pass -Infinity to decrease forever) |
intervalMs | number | 1000 | Interval between updates in milliseconds |
isIncrement | boolean | false | Whether to count up instead of down |
CountdownControllers
Property | Type | Description |
---|---|---|
startCountdown | () => void | Start or resume the countdown |
stopCountdown | () => void | Stop/pause the countdown |
resetCountdown | () => void | Reset to initial value and stop |
Return Value
Returns a tuple with:
count
: Current countdown valuecontrollers
: Object with control functions
Usage Examples
Basic Countdown
const [count, { startCountdown, stopCountdown, resetCountdown }] = useCountdown({
countStart: 30,
})
// Counts down from 30 to 0, stopping automatically at 0
Count Up Timer
const [count, controllers] = useCountdown({
countStart: 0,
countStop: 100,
isIncrement: true,
intervalMs: 500,
})
// Counts up from 0 to 100, updating every 500ms
Custom Interval
const [fastCount, controllers] = useCountdown({
countStart: 10,
intervalMs: 100, // Updates every 100ms for fast countdown
})
Infinite Countdown
const [count, controllers] = useCountdown({
countStart: 0,
countStop: -Infinity, // Never stops automatically
isIncrement: false,
})
// Counts down infinitely (into negative numbers)
Pomodoro Timer
function PomodoroTimer() {
const [minutes, setMinutes] = useState(25)
const [seconds, { startCountdown, stopCountdown, resetCountdown }] = useCountdown({
countStart: minutes * 60,
intervalMs: 1000,
})
const formatTime = (totalSeconds: number) => {
const mins = Math.floor(totalSeconds / 60)
const secs = totalSeconds % 60
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}
useEffect(() => {
if (seconds === 0) {
alert("Time's up!")
}
}, [seconds])
return (
<div>
<h1>{formatTime(seconds)}</h1>
<button onClick={startCountdown}>Start</button>
<button onClick={stopCountdown}>Pause</button>
<button onClick={resetCountdown}>Reset</button>
</div>
)
}
Dynamic Interval
function DynamicTimer() {
const [interval, setInterval] = useState(1000)
const [count, controllers] = useCountdown({
countStart: 60,
intervalMs: interval,
})
return (
<div>
<div>Count: {count}</div>
<input
type="range"
min="100"
max="2000"
value={interval}
onChange={e => setInterval(Number(e.target.value))}
/>
<button onClick={controllers.startCountdown}>Start</button>
</div>
)
}
Multiple Timers
function MultiTimer() {
const [timer1, controls1] = useCountdown({ countStart: 30 })
const [timer2, controls2] = useCountdown({
countStart: 0,
countStop: 60,
isIncrement: true
})
return (
<div>
<div>Countdown: {timer1}</div>
<button onClick={controls1.startCountdown}>Start Timer 1</button>
<div>Count Up: {timer2}</div>
<button onClick={controls2.startCountdown}>Start Timer 2</button>
</div>
)
}
Common Use Cases
- Countdown timers - For games, quizzes, or time-limited activities
- Pomodoro technique - Work/break interval timers
- Loading states - Showing progress or timeout countdowns
- Game mechanics - Cooldowns, respawn timers, round timers
- Session timeouts - User session expiration warnings
- Exercise timers - Workout intervals and rest periods
- Auction timers - Bidding countdown displays
- Event countdowns - Time until events start
Implementation Details
- Built on top of
useBoolean
,useCounter
, anduseInterval
hooks - Automatically stops when
count
reachescountStop
- Uses
useCallback
for optimal performance - Interval is disabled when countdown is stopped (null passed to useInterval)
- Reset functionality stops the timer and resets to initial value
- Supports both increment and decrement modes
- No memory leaks - intervals are properly cleaned up
useCopyToClipboard
React hook for copying text to clipboard with automatic feedback state. Perfect for React applications requiring copy functionality with Next.js integration and TypeScript support.
useCounter
Counter state management with increment, decrement, and reset operations. Perfect for React applications requiring numeric controls with Next.js integration and TypeScript support.