Build a declarative wrapper around setInterval for React. Raw setInterval is imperative and clashes with React's render model — you have to set it up, tear it down, and somehow keep its callback from going stale. useInterval(callback, delay) hides all of that: it runs callback every delay milliseconds, always calls the latest version of the callback, pauses when delay is null, and cleans itself up on unmount. This is the classic hook popularized by Dan Abramov's Making setInterval Declarative.
function useInterval(callback: () => void, delay: number | null): void;
Passing delay = null pauses the interval. The hook returns nothing.
function Clock() {
const [count, setCount] = useState(0);
const [running, setRunning] = useState(true);
// Pausing is just passing null as the delay.
useInterval(() => setCount((c) => c + 1), running ? 1000 : null);
return (
<div>
<span>{count}</span>
<button onClick={() => setRunning((r) => !r)}>
{running ? 'pause' : 'resume'}
</button>
</div>
);
}
// The interval always runs the LATEST callback, even after the component
// re-renders with a new one — no stale closures.
// delay = 100: tick … tick … tick (every 100ms)
// delay = null: (paused — no ticks)
null means paused. A numeric delay schedules the timer; null skips scheduling entirely. Toggling between them pauses and resumes.1000 to 500 should tear down the old timer and start a new one.