npm package: @mdus/use-timer-hooks
Description: React timer hooks — useTimeout and useInterval with cleanup, lifecycle safety, and manual control.
Author: Md Umar Siddique
Latest version: 1.0.1

# useTimer

A lightweight, reusable React hook package that provides two battle-tested utilities: `useTimeout` and `useInterval`. These help you manage time-based side effects in React apps — cleanly and safely.

> Fully React-idiomatic · Auto Cleanup · Functional-safe · Zero Dependencies

## Features

- **Delay Execution (Timeout)** — run code after a specified delay
- **Repeat Execution (Interval)** — run code at a set frequency
- **No Memory Leaks** — auto-clears timers on unmount
- **Safe Callback Handling** — avoids stale closures
- **Manual Control** — start, stop, reset methods
- **Tiny and Efficient** — no dependencies except React

## Installation

```bash
npm install @mdus/use-timer-hooks
# or
yarn add @mdus/use-timer-hooks
```

## API Overview

### `useTimeout(callback, delay)`

Runs a function once after the given delay (in milliseconds).

| Parameter  | Type         | Required | Description                      |
| ---------- | ------------ | -------- | -------------------------------- |
| `callback` | `() => void` | ✅       | Function to run once after delay |
| `delay`    | `number`     | ✅       | Time in ms to wait before firing |

#### Returns

| Key               | Type       | Description                             |
| ----------------- | ---------- | --------------------------------------- |
| `startTimeout()`  | `function` | Start (or restart) the timeout          |
| `stopTimeout()`   | `function` | Cancel the timeout                      |
| `resetTimeout()`  | `function` | Reset the timeout (stop + start)        |
| `isTimeoutActive` | `boolean`  | True while the timeout is counting down |

#### Behavior

- If `delay` is invalid (`null`, `false`, etc), nothing runs
- Automatically stops on component unmount
- Callback is kept in sync (doesn't go stale)

### `useInterval(callback, delay)`

Runs a function **repeatedly** at the given interval (in milliseconds).

| Parameter  | Type         | Required | Description                         |
| ---------- | ------------ | -------- | ----------------------------------- |
| `callback` | `() => void` | ✅       | Function to run on each interval    |
| `delay`    | `number`     | ✅       | Time between runs (in milliseconds) |

#### Returns

| Key                | Type       | Description                        |
| ------------------ | ---------- | ---------------------------------- |
| `startInterval()`  | `function` | Starts the interval                |
| `stopInterval()`   | `function` | Stops the interval                 |
| `resetInterval()`  | `function` | Stops and restarts the interval    |
| `isIntervalActive` | `boolean`  | True while the interval is running |

## Examples

### Basic Timeout

```jsx
import { useTimeout } from "@mdus/use-timer-hooks";

function Message() {
  const [show, setShow] = useState(true);

  // Hide message after 3s
  useTimeout(() => setShow(false), 3000);

  return show ? <p>Hello! This disappears in 3 seconds.</p> : null;
}
```

### Countdown Using Interval

```jsx
import { useInterval } from "@mdus/use-timer-hooks";

function Countdown() {
  const [seconds, setSeconds] = useState(10);

  const { stopInterval, isIntervalActive } = useInterval(() => {
    setSeconds((prev) => {
      if (prev <= 1) {
        stopInterval(); // Stop when we hit 0
        return 0;
      }
      return prev - 1;
    });
  }, 1000);

  return (
    <p>
      Countdown: {seconds} {isIntervalActive ? "" : "(Done)"}
    </p>
  );
}
```

### Debounced Search Input

```jsx
import { useTimeout } from "@mdus/use-timer-hooks";

function DebouncedSearch({ value, onSearch }) {
  const { resetTimeout } = useTimeout(() => {
    onSearch(value);
  }, 500); // debounce 500ms

  useEffect(() => {
    resetTimeout(); // re-trigger on value change
  }, [value]);

  return null;
}
```

## Internal Notes

- We use `useRef` to store the latest version of your callback to prevent stale closure issues.
- Both hooks automatically **clear timers** when the component unmounts — you don't need to worry about leaks or race conditions.
- Manual `startX()`, `stopX()`, and `resetX()` functions give you full control.

## Folder Structure

```
use-timer-hooks/
├── src/
│   └── useTimer.js
├── dist/
│   └── index.js
├── package.json
├── README.md
└── LICENSE
```

## Author

**Md Umar Siddique**  
Frontend-first engineer building real-world tools with long-term value.

- GitHub: [@umarSiddique010](https://github.com/umarSiddique010)
- LinkedIn: [md-umar-siddique](https://linkedin.com/in/md-umar-siddique)
- Twitter/X: [@umarSiddique010](https://twitter.com/umarSiddique010)

- Dev.to: [@umarSiddique010](https://dev.to/umarsiddique010)

## Contributing

Pull requests are welcome! If you'd like to improve anything or need another timing hook, open an issue or PR.

## License

MIT License — use freely, credit appreciated.