All hooks / Timers

useTimeout

188 B minified and brotliedSourceMarkdown✓ Works in all modern browsers

Calls callback once, delayMs after mount or after delayMs changes. Pass null to cancel. Always calls the latest callback. Cleared on unmount. Nothing runs on the server.

Returns restart, which starts the delay over: for a "Saved ✓" label that should stay for 2s after the latest save, not the first one.

Import

import { useTimeout } from '@vincent.ri/react-tils'
// or only this hook
import { useTimeout } from '@vincent.ri/react-tils/useTimeout'

Usage

function Toast({ onClose }: { onClose: () => void }) {
  const [hovered, setHovered] = useState(false)
  useTimeout(onClose, hovered ? null : 5000)
  return <div onPointerEnter={() => setHovered(true)} onPointerLeave={() => setHovered(false)}>Saved</div>
}

// Show "Saved" for 2s after the latest save.
const [saved, setSaved] = useState(false)
const restart = useTimeout(() => setSaved(false), 2000)
const onSave = () => { setSaved(true); restart() }

Live demo

Shows for 2s after the latest save.

not saved

When to use it

Auto-dismissing a toast, hiding a "Saved" or "Copied" label, or a delay before showing a spinner. Pause a toast on hover by passing null.

When not to

It should repeat; use useInterval. To wait until the user stops typing, use useDebouncedCallback or useDebouncedValue. For "Copied!" after copying, useCopyToClipboard already resets itself.

API

function useTimeout(callback: () => void, delayMs: number | null): () => void
ParameterDescription
callbackCalled when the delay ends. Can change every render.
delayMsMilliseconds to wait, or null to cancel.

Returns restart: start the delay over. Does nothing while delayMs is null.

Browser support

Uses only long-established browser features, so it works wherever React does.

First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).

Coming from another library?

Other libraries call this useTimeoutFn.