React useCountdown Hook
React useCountdown hook for countdown timers. Flexible timer with start/stop/reset controls using TypeScript support for Next.js applications.
Timer Not Accurate?
Join our Discord community for help from other developers.
Ever built a countdown timer and realized you're juggling setInterval, clearInterval, state management, boundary checks, and cleanup logic? You know the drill—track the interval ID, handle component unmounts, deal with stale closures. This free open source React useCountdown custom hook handles all that timer complexity so you can focus on your UI instead of fighting with JavaScript timing quirks in your React applications.
useCountdown showcase
Flexible countdown timer with full control:
This free open source React hook simplifies timer management with TypeScript support for modern JavaScript applications. Whether you're building pomodoro timers, game countdowns, or session timeouts in your Next.js projects, this React hook keeps your timing logic clean and reliable.
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
Why most countdown implementations suck
Look, you could manually manage setInterval, track the interval ID, handle cleanup on unmount, and deal with React's closure issues. But after debugging the third "why is my timer jumping" bug, you'll appreciate having this handled properly.
Most developers forget to clear intervals when components unmount, causing memory leaks in React applications. Or they use inline functions that re-register timers on every render, creating performance issues. Some skip proper closure handling and wonder why their timer callbacks have stale values in TypeScript components.
The React hook automatically manages the entire timer lifecycle—proper cleanup, pause/resume functionality, and boundary checking. No more forgotten clearInterval calls or stale closure bugs in Next.js projects.
Plus it handles both countdown and count-up modes, custom intervals, and auto-stop conditions—all the stuff you'd eventually need to add anyway in JavaScript applications.
This free open source React hook handles the timer boilerplate while you focus on building features. Whether you're creating React applications, Next.js projects, or TypeScript codebases, this custom hook keeps your countdown logic bulletproof.
Features
- Flexible direction - Count down or count up with
isIncrement
option in React applications - Configurable interval - Set custom intervals in milliseconds for TypeScript components
- Auto-stop - Automatically stops when reaching the target value in Next.js projects
- Full control - Start, stop, and reset functionality for JavaScript development
- Custom boundaries - Set custom start and stop values with proper validation
- Performance optimized - Uses efficient interval management to prevent memory leaks
- TypeScript support - Complete type definitions for all options and return values
- Free open source - Designed for modern React development workflows
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
When you'll actually use this
Real talk—this isn't for displaying the current time or simple delays in React applications. For those, use Date objects or setTimeout. But when you need interactive timers with pause/resume, this React hook shines in Next.js projects.
Perfect for:
- Countdown timers - Games, quizzes, or time-limited activities built with TypeScript
- Pomodoro technique - Work/break interval timers in productivity apps using React patterns
- Loading states - Timeout countdowns with visual progress indicators in JavaScript applications
- Game mechanics - Cooldowns, respawn timers, round timers for React gaming interfaces
- Session timeouts - User session expiration warnings in Next.js applications
- Exercise timers - Workout intervals and rest periods with TypeScript validation
- Auction timers - Bidding countdown displays with real-time updates in React components
- Event countdowns - Time until launches or deadlines using JavaScript timing
Common gotchas
JavaScript timers aren't perfectly accurate: setInterval can drift, especially with background tabs in React applications. For mission-critical timing, you'd need to track actual elapsed time with Date.now() in TypeScript components.
React 18 batches state updates: Rapid interval changes might not render every single value in Next.js projects. This is usually fine for UI timers but worth knowing for debugging.
Background tab throttling: Browsers throttle intervals in background tabs to save resources in JavaScript applications. Your timer might slow down when users switch tabs—a browser feature, not a bug.
Automatic boundary stopping: When it reaches countStop, the timer stops in React components. If you need it to continue or loop, you'll need to handle that in your component with useEffect.
Memory leaks from improper cleanup: The most common mistake is forgetting interval cleanup when components unmount in TypeScript projects. This React hook handles the lifecycle automatically.
Related hooks you will also like
useInterval
Interval management with automatic cleanup and pause functionality
useTimeout
Timeout management with automatic cleanup and cancellation
useCounter
Counter state management with increment, decrement, and reset helpers
useBoolean
Boolean state management for timer start/stop states
useStep
Step-by-step state management for multi-phase timers
useLocalStorage
Persist timer states and preferences in localStorage
Questions you might have
React useCopyToClipboard Hook
React useCopyToClipboard hook for clipboard operations. Copy text with automatic feedback state using TypeScript support for Next.js apps.
React useCounter Hook
React useCounter hook for numeric state management. Increment, decrement, and reset controls with TypeScript support for Next.js applications.