Overview
The useInterval hook calls a callback function on a repeating interval. It handles cleanup automatically and can be paused by passing null as the delay.
Signature
function useInterval(callback: () => void, delay: number | null): void
Parameters
Function to call on each tick of the interval
Interval in milliseconds between each callback execution. Pass null to pause the interval.
Examples
Basic counter
import { useState } from 'react';
import { useInterval } from '@kivora/react';
function Counter() {
const [count, setCount] = useState(0);
const [running, setRunning] = useState(true);
useInterval(() => {
setCount(c => c + 1);
}, running ? 1000 : null);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setRunning(!running)}>
{running ? 'Pause' : 'Start'}
</button>
</div>
);
}
Clock component
import { useState } from 'react';
import { useInterval } from '@kivora/react';
function Clock() {
const [time, setTime] = useState(new Date());
useInterval(() => {
setTime(new Date());
}, 1000);
return (
<div>
{time.toLocaleTimeString()}
</div>
);
}
Auto-refresh data
import { useState } from 'react';
import { useInterval } from '@kivora/react';
function LiveData() {
const [data, setData] = useState(null);
const [isActive, setIsActive] = useState(true);
const fetchData = async () => {
const response = await fetch('/api/data');
const json = await response.json();
setData(json);
};
useInterval(() => {
fetchData();
}, isActive ? 5000 : null);
return (
<div>
<button onClick={() => setIsActive(!isActive)}>
{isActive ? 'Stop Refresh' : 'Start Refresh'}
</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
Progress animation
import { useState } from 'react';
import { useInterval } from '@kivora/react';
function ProgressBar() {
const [progress, setProgress] = useState(0);
useInterval(() => {
setProgress(p => {
if (p >= 100) return 0; // Reset when complete
return p + 1;
});
}, 50);
return (
<div style={{ width: '100%', backgroundColor: '#eee' }}>
<div
style={{
width: `${progress}%`,
height: '20px',
backgroundColor: '#4CAF50',
transition: 'width 0.05s linear'
}}
/>
</div>
);
}
Polling with pause
import { useState, useEffect } from 'react';
import { useInterval } from '@kivora/react';
function DataPoller() {
const [data, setData] = useState([]);
const [isPaused, setIsPaused] = useState(false);
const pollData = async () => {
const res = await fetch('/api/updates');
const updates = await res.json();
setData(prev => [...prev, ...updates]);
};
// Initial fetch
useEffect(() => {
pollData();
}, []);
// Poll every 3 seconds when not paused
useInterval(() => {
pollData();
}, isPaused ? null : 3000);
return (
<div>
<button onClick={() => setIsPaused(!isPaused)}>
{isPaused ? 'Resume' : 'Pause'} Polling
</button>
<ul>
{data.map((item, i) => <li key={i}>{item}</li>)}
</ul>
</div>
);
}
Use Cases
- Timers & counters: Count down or up at regular intervals
- Clocks: Display current time with second precision
- Auto-refresh: Periodically fetch new data from an API
- Animations: Create frame-based animations
- Polling: Check for updates at regular intervals
- Game loops: Update game state on a fixed schedule
Notes
- The interval automatically cleans up when the component unmounts
- Pass
null as the delay to pause the interval without unmounting
- The callback ref is updated on every render to always use the latest version
- This hook is based on Dan Abramov’s popular useInterval implementation