Join our Discord Community

useTimeout

React hook for declarative setTimeout management with automatic cleanup and dynamic delay control. Perfect for React applications requiring timed actions with Next.js integration and TypeScript support.

Loading component...

Installation

npx shadcn@latest add https://www.shadcn.io/registry/use-timeout.json
npx shadcn@latest add https://www.shadcn.io/registry/use-timeout.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/use-timeout.json
bunx shadcn@latest add https://www.shadcn.io/registry/use-timeout.json

Advanced Usage

Loading component...

Demonstrates timeout control with conditional execution - a bomb defusing game where you can pause/resume the timer.

Features

  • Declarative timeout management with automatic cleanup and dependency tracking
  • Dynamic delay control including pause/cancel functionality using null values
  • Latest callback execution ensuring most recent function is always called
  • Automatic memory management with proper cleanup on unmount and re-renders
  • TypeScript support with comprehensive type definitions and IntelliSense
  • Zero external dependencies with lightweight React-only implementation

Use Cases

This free open source React hook works well for:

  • Auto-save functionality - Delay save operations and cancel on new changes
  • Delayed notifications - Show/hide messages with automatic timeout
  • Game mechanics - Implement timers, countdowns, and time-based actions
  • Debounced actions - Delay API calls, search queries, and user inputs
  • UI animations - Control timed animations and transitions in React apps
  • Loading states - Implement timeout-based loading indicators and fallbacks

API Reference

useTimeout

ParameterTypeDefaultDescription
callback() => void-Function to execute after the delay
delaynumber | null-Delay in milliseconds, or null to cancel/pause

Usage Patterns

Basic Timer

import { useTimeout } from '@repo/use-timeout';
import { useState } from 'react';

function Timer() {
  const [hasElapsed, setHasElapsed] = useState(false);

  useTimeout(() => {
    setHasElapsed(true);
  }, 3000);

  return (
    <div>
      {hasElapsed ? 'Time is up!' : 'Timer is running...'}
    </div>
  );
}

Conditional Timeout

import { useTimeout } from '@repo/use-timeout';
import { useState } from 'react';

function ConditionalTimer() {
  const [isActive, setIsActive] = useState(true);
  const [message, setMessage] = useState('Waiting...');

  // Pass null to pause/cancel the timeout
  useTimeout(() => {
    setMessage('Timeout executed!');
  }, isActive ? 2000 : null);

  return (
    <div>
      <p>{message}</p>
      <button onClick={() => setIsActive(!isActive)}>
        {isActive ? 'Pause' : 'Resume'} Timer
      </button>
    </div>
  );
}

Dynamic Delay

import { useTimeout } from '@repo/use-timeout';
import { useState } from 'react';

function DynamicTimer() {
  const [delay, setDelay] = useState(1000);
  const [count, setCount] = useState(0);

  useTimeout(() => {
    setCount(c => c + 1);
  }, delay);

  return (
    <div>
      <p>Count: {count}</p>
      <input
        type="number"
        value={delay}
        onChange={(e) => setDelay(Number(e.target.value))}
        placeholder="Delay in ms"
      />
    </div>
  );
}

API Reference

useTimeout(callback, delay)

  • callback: () => void - The function to execute after the delay
  • delay: number | null - Delay in milliseconds, or null to cancel/pause

Returns: void

Parameters

  • callback: The function that will be called after the specified delay
  • delay:
    • number - Execute callback after this many milliseconds
    • null - Cancel/pause the timeout (useful for conditional execution)

Use Cases

Auto-save Feature

useTimeout(() => {
  saveDocument();
}, hasUnsavedChanges ? 2000 : null);

Show/Hide Messages

useTimeout(() => {
  setShowMessage(false);
}, showMessage ? 5000 : null);

Delayed API Calls

useTimeout(() => {
  fetchData();
}, searchQuery ? 300 : null); // Debounce search

Game Mechanics

// Game timer that can be paused
useTimeout(() => {
  endGame();
}, isGameActive ? timeRemaining : null);

Implementation Notes

  • Automatic Cleanup: The timeout is automatically cleared when the component unmounts or when the delay changes
  • Latest Callback: Uses useRef to ensure the most recent callback is always executed
  • Conditional Execution: Passing null as delay prevents the timeout from being set
  • Re-triggering: When delay changes, the previous timeout is cleared and a new one is set
  • Performance: No memory leaks - timeouts are properly cleaned up

Common Patterns

One-time Delay

// Execute once after component mounts
useTimeout(() => {
  console.log('Component loaded');
}, 1000);

Conditional Execution

// Only run timeout when condition is met
useTimeout(
  () => performAction(),
  shouldRun ? 2000 : null
);

Reset Timer

// Reset timer by changing delay
const [resetKey, setResetKey] = useState(0);

useTimeout(() => {
  // This will re-trigger when resetKey changes
}, 3000);

// Reset the timer
const resetTimer = () => setResetKey(k => k + 1);