Join our Discord Community

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:

Loading component...

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

PropertyTypeDefaultDescription
countStartnumber-Starting number for the countdown (required)
countStopnumber0Stopping number (pass -Infinity to decrease forever)
intervalMsnumber1000Interval between updates in milliseconds
isIncrementbooleanfalseWhether to count up instead of down

CountdownControllers

PropertyTypeDescription
startCountdown() => voidStart or resume the countdown
stopCountdown() => voidStop/pause the countdown
resetCountdown() => voidReset to initial value and stop

Return Value

Returns a tuple with:

  • count: Current countdown value
  • controllers: 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.

Questions you might have