JAVASCRIPT
Create a Flexible Countdown Timer Hook
Implement `useCountdown`, a versatile React hook for managing precise countdown timers, ideal for OTPs, event deadlines, or game mechanics. It handles seconds, minutes, and hours, stopping accurately at zero.
import { useState, useEffect, useRef } from 'react';
// Helper function to format time (optional, for display)
const formatTime = (seconds) => {
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = seconds % 60;
return [h, m, s]
.map(v => v < 10 ? "0" + v : v)
.filter((v, i) => v !== "00" || i > 0)
.join(":");
};
const useCountdown = (initialSeconds) => {
const [secondsLeft, setSecondsLeft] = useState(initialSeconds);
const intervalRef = useRef();
useEffect(() => {
if (secondsLeft <= 0) {
clearInterval(intervalRef.current);
return;
}
intervalRef.current = setInterval(() => {
setSecondsLeft((prevSeconds) => prevSeconds - 1);
}, 1000);
return () => clearInterval(intervalRef.current);
}, [secondsLeft]); // Dependency on secondsLeft ensures correct cleanup and restart if initialSeconds changes
const start = (newSeconds = initialSeconds) => {
clearInterval(intervalRef.current); // Clear any existing timer
setSecondsLeft(newSeconds);
};
const stop = () => {
clearInterval(intervalRef.current);
setSecondsLeft(0); // Optionally reset to 0 or keep current value
};
const reset = () => {
clearInterval(intervalRef.current);
setSecondsLeft(initialSeconds);
};
return { secondsLeft, start, stop, reset, format: formatTime(secondsLeft) };
};
// Example Usage:
// function MyCountdownComponent() {
// const { secondsLeft, start, stop, reset, format } = useCountdown(60); // 60 seconds
//
// return (
// <div>
// <h1>Countdown: {format}</h1>
// <p>Seconds remaining: {secondsLeft}</p>
// <button onClick={() => start(120)}>Start 120s</button>
// <button onClick={stop}>Stop</button>
// <button onClick={reset}>Reset</button>
// </div>
// );
// }
How it works: The `useCountdown` hook provides robust functionality for managing a countdown timer. It takes an `initialSeconds` value and returns the `secondsLeft`, along with `start`, `stop`, and `reset` functions. Using `setInterval` and `useRef` for the interval ID, it ensures that the timer updates every second and correctly clears itself when the countdown reaches zero or the component unmounts. The optional `formatTime` helper demonstrates how to display the remaining time in a user-friendly `HH:MM:SS` format.