← Back to all snippets
JAVASCRIPT

Custom useCountdown Hook for Timer Functionality

A flexible React custom hook to create and manage countdown timers, perfect for displaying time remaining, limited-time offers, or game mechanics.

import { useState, useEffect, useCallback } from 'react';

const useCountdown = (initialSeconds = 60, autoStart = false) => {
  const [secondsLeft, setSecondsLeft] = useState(initialSeconds);
  const [isRunning, setIsRunning] = useState(autoStart);

  const start = useCallback(() => setIsRunning(true), []);
  const stop = useCallback(() => setIsRunning(false), []);
  const reset = useCallback(() => {
    setSecondsLeft(initialSeconds);
    setIsRunning(false);
  }, [initialSeconds]);

  useEffect(() => {
    if (!isRunning) {
      return;
    }

    if (secondsLeft <= 0) {
      setIsRunning(false);
      return;
    }

    const timerId = setInterval(() => {
      setSecondsLeft(prevSeconds => prevSeconds - 1);
    }, 1000);

    return () => clearInterval(timerId); // Cleanup on unmount or if dependencies change
  }, [isRunning, secondsLeft]); // Re-run effect when running status or secondsLeft changes

  return { secondsLeft, isRunning, start, stop, reset };
};

export default useCountdown;

// How to use:
// import useCountdown from './useCountdown';
// function CountdownDisplay() {
//   const { secondsLeft, isRunning, start, stop, reset } = useCountdown(10, true);
//   return (
//     <div>
//       <p>Time left: {secondsLeft} seconds</p>
//       <p>Status: {isRunning ? 'Running' : 'Stopped'}</p>
//       <button onClick={start} disabled={isRunning}>Start</button>
//       <button onClick={stop} disabled={!isRunning}>Stop</button>
//       <button onClick={reset}>Reset</button>
//     </div>
//   );
// }
How it works: This custom hook provides robust countdown timer functionality. It manages the `secondsLeft` and `isRunning` states. The `useEffect` hook handles the `setInterval` logic: when `isRunning` is true and `secondsLeft` is greater than zero, it decrements the `secondsLeft` every second. The effect cleans up the `setInterval` using `clearInterval` when the component unmounts or `isRunning` becomes false or `secondsLeft` reaches zero. It also exposes `start`, `stop`, and `reset` functions to control the timer, making it highly reusable for various timer-related UI elements.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs