Overview
The useTimeout hook provides a declarative way to manage setTimeout with programmatic control. It returns methods to start, stop, and reset the timeout.
Signature
function useTimeout(
callback: () => void,
delay: number,
autoStart?: boolean
): UseTimeoutReturn
Parameters
Function to call after the delay expires
Delay in milliseconds before the callback is invoked
Whether to start the timeout automatically on mount
Returns
Start or restart the timeout
Reset the timeout (equivalent to calling start())
Type Definitions
interface UseTimeoutReturn {
start: () => void;
stop: () => void;
reset: () => void;
}
Examples
Flash message
import { useState } from 'react';
import { useTimeout } from '@kivora/react';
function FlashMessage() {
const [visible, setVisible] = useState(false);
const { reset } = useTimeout(() => {
setVisible(false);
}, 2000, false);
const showMessage = () => {
setVisible(true);
reset(); // Start the timeout
};
return (
<div>
<button onClick={showMessage}>Show Message</button>
{visible && <div className="flash">This will disappear soon!</div>}
</div>
);
}
Auto-logout timer
import { useTimeout } from '@kivora/react';
function SessionManager() {
const { reset, stop } = useTimeout(() => {
// Log out user after 5 minutes of inactivity
logout();
}, 5 * 60 * 1000);
const handleActivity = () => {
reset(); // Reset the timer on user activity
};
const handleLogout = () => {
stop(); // Cancel auto-logout
logout();
};
return (
<div
onMouseMove={handleActivity}
onKeyPress={handleActivity}
onClick={handleActivity}
>
<button onClick={handleLogout}>Logout</button>
{/* App content */}
</div>
);
}
Delayed search
import { useState } from 'react';
import { useTimeout } from '@kivora/react';
function SearchWithDelay() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const { reset } = useTimeout(async () => {
if (query) {
const data = await fetchResults(query);
setResults(data);
}
}, 500, false);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setQuery(e.target.value);
reset(); // Reset timeout on each keystroke
};
return (
<div>
<input value={query} onChange={handleChange} />
<ul>
{results.map(r => <li key={r.id}>{r.name}</li>)}
</ul>
</div>
);
}
import { useState } from 'react';
import { useTimeout } from '@kivora/react';
function TooltipButton() {
const [showTooltip, setShowTooltip] = useState(false);
const { start, stop } = useTimeout(() => {
setShowTooltip(true);
}, 500, false);
const handleMouseEnter = () => {
start();
};
const handleMouseLeave = () => {
stop();
setShowTooltip(false);
};
return (
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
style={{ position: 'relative' }}
>
<button>Hover me</button>
{showTooltip && (
<div className="tooltip">Helpful information</div>
)}
</div>
);
}
Notification system
import { useState } from 'react';
import { useTimeout } from '@kivora/react';
function Notification({ message, duration = 3000 }) {
const [visible, setVisible] = useState(true);
const { stop } = useTimeout(() => {
setVisible(false);
}, duration);
const handleDismiss = () => {
stop();
setVisible(false);
};
if (!visible) return null;
return (
<div className="notification">
{message}
<button onClick={handleDismiss}>×</button>
</div>
);
}
Use Cases
- Flash messages: Show temporary notifications or alerts
- Auto-logout: Implement session timeouts
- Delayed actions: Execute functions after user inactivity
- Tooltips: Show help text after hovering for a duration
- Toast notifications: Auto-dismiss messages
- Debounced operations: Delay execution with manual control
Notes
- The timeout automatically cleans up when the component unmounts
- Calling
start() will cancel any existing timeout before starting a new one
- The callback ref is always kept up-to-date, so you don’t need to worry about stale closures
reset() is equivalent to calling start() - it restarts the timer from the beginning