Effects

useTimeout

Runs a callback once after a delay; cancel by passing null.

Demo

Idle — arm the timeout

delay
null

Usage

use-timeout.tsxtsx
import { useState } from "react";
import { useTimeout } from "hookli";

export function Demo() {
  const [visible, setVisible] = useState(false);
  const [delay, setDelay] = useState<number | null>(null);

  useTimeout(() => {
    setVisible(true);
    setDelay(null);
  }, delay);

  return (
    <div>
      <button onClick={() => setDelay(2000)}>Reveal in 2s</button>
      {visible && <p>Here!</p>}
    </div>
  );
}

API

useTimeout.d.tsts
useTimeout(callback: () => void, delay: number | null): void

Parameters

NameTypeDefaultDescription
callback() => voidRuns once after the delay elapses. The hook keeps a ref to the latest callback, so it always fires with fresh state.
delaynumber | nullMilliseconds to wait before firing. Pass null to disable — a change to null before the delay elapses cancels the pending timeout.

Returns

This hook returns nothing.

Hook

The implementation, straight from hookli. Copy it, or install the package.

src/hooks/use-timeout/use-timeout.tstsx
import { useEffect, useRef } from "react";

export const useTimeout = (callback: () => void, delay: number | null) => {
  const savedCallback = useRef(callback);

  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  useEffect(() => {
    if (delay === null) return;
    const id = setTimeout(() => savedCallback.current(), delay);
    return () => clearTimeout(id);
  }, [delay]);
};

View source on GitHub

Related hooks