@danielsledz/react-countdown-hook
v1.1.3
Published
A simple React hook for creating countdown timers to any target date or time
Maintainers
Readme
🕒 @danielsledz/react-countdown-hook
A simple React hook for creating countdown timers to any target date or time.
🚀 Installation
npm install @danielsledz/react-countdown-hook
# or
yarn add @danielsledz/react-countdown-hook
# or
pnpm add @danielsledz/react-countdown-hook🧠 Usage
Basic Example
import { useCountdown } from "@danielsledz/react-countdown-hook";
const MyComponent = () => {
const { timeLeft, isPaused, togglePause, error } = useCountdown(
"2025-12-31T23:59:59"
);
if (error) return <p>Error: {error}</p>;
return (
<div>
<p>
{timeLeft.direction} {timeLeft.days}d {timeLeft.hours}h{" "}
{timeLeft.minutes}m {timeLeft.seconds}s
</p>
<button onClick={togglePause}>{isPaused ? "Resume" : "Pause"}</button>
</div>
);
};Advanced Example with Date Object
import { useCountdown } from "@danielsledz/react-countdown-hook";
const MyComponent = () => {
const targetDate = new Date("2025-12-31T23:59:59");
const { timeLeft, isPaused, togglePause, error } = useCountdown(targetDate);
if (error) return <p>Error: {error}</p>;
const formatTime = (time: number) => time.toString().padStart(2, "0");
return (
<div>
<h2>Countdown to New Year 2026</h2>
<div style={{ fontSize: "2rem", fontFamily: "monospace" }}>
{timeLeft.direction === "-" ? "Time remaining:" : "Time since:"}
<br />
{formatTime(timeLeft.days)}:{formatTime(timeLeft.hours)}:
{formatTime(timeLeft.minutes)}:{formatTime(timeLeft.seconds)}
</div>
<button onClick={togglePause}>
{isPaused ? "▶️ Resume" : "⏸️ Pause"}
</button>
</div>
);
};Event Countdown Example
import { useCountdown } from "@danielsledz/react-countdown-hook";
const EventCountdown = () => {
const { timeLeft, isPaused, togglePause, error } = useCountdown(
"2025-06-15T18:00:00"
);
if (error) return <p>Error: {error}</p>;
const isEventPassed = timeLeft.direction === "+";
return (
<div>
<h3>Summer Conference 2025</h3>
{isEventPassed ? (
<p>Event has passed! It's been {timeLeft.days} days since the event.</p>
) : (
<div>
<p>Event starts in:</p>
<div>
{timeLeft.days} days, {timeLeft.hours} hours, {timeLeft.minutes}{" "}
minutes, {timeLeft.seconds} seconds
</div>
<button onClick={togglePause}>
{isPaused ? "Resume Countdown" : "Pause Countdown"}
</button>
</div>
)}
</div>
);
};📦 API
useCountdown(targetDate: string | Date): CountdownHook
Parameters:
targetDate: The date and time to count down to (string or Date object).
Returns:
| Name | Type | Description |
| ------------- | ---------------------------------------------- | ----------------------------------------------------------------- |
| timeLeft | { days, hours, minutes, seconds, direction } | Remaining time and countdown direction (- = future, + = past) |
| isPaused | boolean | Whether the countdown is paused |
| togglePause | () => void | Function to toggle pause/resume |
| error | string \| null | Error message if invalid input |
Types
interface TimeLeft {
days: number;
hours: number;
minutes: number;
seconds: number;
direction: string; // "-" for future, "+" for past
}
interface CountdownHook {
timeLeft: TimeLeft;
isPaused: boolean;
togglePause: () => void;
error: string | null;
}⚠️ Error Handling
If the target date is invalid (e.g., useCountdown("invalid-date")), the error field will contain an appropriate message.
const { error } = useCountdown("invalid-date");
if (error) {
console.log(error); // "Invalid target date."
}🧪 Testing
The package includes comprehensive unit and integration tests using Vitest and React Testing Library.
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverageTest Coverage
The test suite covers:
- ✅ Basic countdown functionality
- ✅ Pause/resume functionality
- ✅ Error handling for invalid dates
- ✅ Time calculations accuracy
- ✅ Edge cases and boundary conditions
- ✅ Integration scenarios
- ✅ Memory leak prevention
🔧 Development
# Install dependencies
npm install
# Build the package (CommonJS + ESM)
npm run build
# Build TypeScript declarations
npm run build:types
# Watch for changes during development
npm run dev
# Clean build directory
npm run clean
# Run tests
npm test
# Run tests with coverage
npm run test:coverageBuild Output
The build process generates:
dist/index.js- CommonJS bundledist/index.esm.js- ES Module bundledist/index.d.ts- TypeScript declarations
📄 License
MIT © 2025 Daniel Śledź
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Development Setup
- Fork the repository
- Clone your fork
- Install dependencies:
npm install - Make your changes
- Add tests for new functionality
- Run tests:
npm test - Build the package:
npm run build - Submit a pull request
