useTimeout()
Last updated: 24/04/2026
Overview
useTimeout registers setTimeout(() => callbackRef.current(), delay) in an effect. The latest callback is always kept in a ref (first effect), so the scheduled timeout does not need a stale closure, but the call on fire uses whatever callback was on last render. **delay is a dependency of the second effect: each change clears the old timer and starts a new one. If delay is null, the hook skips scheduling (useful to pause). The cleanup clears the ID on unmount or before rescheduling. It does not track loading or return a cancel handle-null the delay in parent state to cancel. Uses **globalThis.setTimeout**.
What it accepts
callback:() => voiddelay:number | null- whennull, no timer runs
Usage
After 1.2 s show a “Ready” message once; a “Cancel” button sets delay to null.
import { useState } from 'react'
import useTimeout from '@dedalik/use-react/useTimeout'
function Example() {
const [delay, setDelay] = useState<number | null>(1200)
const [message, setMessage] = useState('Waiting…')
useTimeout(() => {
setMessage('Ready')
}, delay)
return (
<div>
<p>{message}</p>
{delay != null && (
<button type='button' onClick={() => setDelay(null)}>
Cancel timer
</button>
)}
</div>
)
}
export default function Demo() {
return <Example />
}API Reference
useTimeout
Signature: useTimeout(callback: () => void, delay: number | null): void
Copy-paste hook
TypeScript
import { useEffect, useRef } from 'react'
export default function useTimeout(callback: () => void, delay: number | null) {
const callbackRef = useRef(callback)
useEffect(() => {
callbackRef.current = callback
}, [callback])
useEffect(() => {
if (delay == null) return
const timeoutId = globalThis.setTimeout(() => {
callbackRef.current()
}, delay)
return () => globalThis.clearTimeout(timeoutId)
}, [delay])
}JavaScript
import { useEffect, useRef } from 'react'
export default function useTimeout(callback, delay) {
const callbackRef = useRef(callback)
useEffect(() => {
callbackRef.current = callback
}, [callback])
useEffect(() => {
if (delay == null) return
const timeoutId = globalThis.setTimeout(() => {
callbackRef.current()
}, delay)
return () => globalThis.clearTimeout(timeoutId)
}, [delay])
}