Serafim

useDebounce

Component 42

About

A hook that returns a debounced version of the provided value. The debounced value will only update after the specified delay has passed without any new changes to the original value.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds useDebounce to your project and fits it to your theme.

Code

How useDebounce is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import { useState, useEffect } from 'react';
import { useDebounce } from '@/components/hooks/use-debounce';
import { Input } from "@/components/ui/input";

// Simple Input Demo
export function DebounceInputDemo() {
  const [inputValue, setInputValue] = useState('');
  const debouncedValue = useDebounce(inputValue, 500);
  const [apiResult, setApiResult] = useState('');

  useEffect(() => {
    // Имитация API запроса
    if (debouncedValue) {
      setApiResult(`Making API call with: ${debouncedValue}`);
    }
  }, [debouncedValue]);

  return (
    <div className="flex flex-col gap-4 w-[300px]">
      <div className="space-y-2">
        <p className="text-sm text-muted-foreground">
          Type something to see debounce in action
        </p>
        <Input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
          placeholder="Start typing..."
        />
      </div>
      <div className="space-y-2">
        <p className="text-sm font-medium">Current value:</p>
        <p className="text-sm text-muted-foreground">{inputValue}</p>
      </div>
      <div className="space-y-2">
        <p className="text-sm font-medium">Debounced value:</p>
        <p className="text-sm text-muted-foreground">{debouncedValue}</p>
      </div>
      <div className="space-y-2">
        <p className="text-sm font-medium">API Response:</p>
        <p className="text-sm text-muted-foreground">{apiResult}</p>
      </div>
    </div>
  );
}

// Search Demo
export function DebounceSearchDemo() {
  const [search, setSearch] = useState('');
  const debouncedSearch = useDebounce(search, 500);
  const [results, setResults] = useState<string[]>([]);
  const [isSearching, setIsSearching] = useState(false);

  // Имитация поиска
  useEffect(() => {
    if (debouncedSearch) {
      setIsSearching(true);
      // Имитация API запроса
      setTimeout(() => {
        setResults([
          `Result 1 for "${debouncedSearch}"`,
          `Result 2 for "${debouncedSearch}"`,
          `Result 3 for "${debouncedSearch}"`,
        ]);
        setIsSearching(false);
      }, 1000);
    } else {
      setResults([]);
    }
  }, [debouncedSearch]);

  return (
    <div className="flex flex-col gap-4 w-[300px]">
      <div className="space-y-2">
        <p className="text-sm text-muted-foreground">
          Search with debounce
        </p>
        <Input
          type="search"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          placeholder="Search..."
        />
      </div>
      <div className="space-y-2">
        {isSearching ? (
          <p className="text-sm">Searching...</p>
        ) : (
          results.map((result, index) => (
            <p key={index} className="text-sm">
              {result}
            </p>
          ))
        )}
      </div>
    </div>
  );
}

// Counter Demo
export function DebounceCounterDemo() {
  const [count, setCount] = useState(0);
  const debouncedCount = useDebounce(count, 1000);
  const [savedCounts, setSavedCounts] = useState<number[]>([]);

  useEffect(() => {
    // Сохраняем значение только когда debouncedCount изменился
    if (debouncedCount > 0) {
      setSavedCounts(prev => [...prev, debouncedCount]);
    }
  }, [debouncedCount]);

  return (
    <div className="flex flex-col gap-4 w-[300px]">
      <div className="space-y-2">
        <p className="text-sm text-muted-foreground">
          Click rapidly to see debounce effect
        </p>
        <Button
          onClick={() => setCount(c => c + 1)}
          className="w-full"
        >
          Increment: {count}
        </Button>
      </div>
      <div className="space-y-2">
        <p className="text-sm font-medium">Debounced count:</p>
        <p className="text-sm text-muted-foreground">{debouncedCount}</p>
      </div>
      <div className="space-y-2">
        <p className="text-sm font-medium">Saved counts:</p>
        <div className="flex flex-wrap gap-2">
          {savedCounts.map((savedCount, index) => (
            <span
              key={index}
              className="text-sm bg-muted px-2 py-1 rounded"
            >
              {savedCount}
            </span>
          ))}
        </div>
      </div>
    </div>
  );
}

More by Serafim

View all
  • Spline Scene

    Spline Scene

    9.5K
  • Testimonials with Marquee

    Testimonials with Marquee

    2.3K
  • Gradient Button

    Gradient Button

    1.9K
  • Pixel Canvas

    Pixel Canvas

    900
  • Animated Blur Number

    Animated Blur Number

    830
  • Empty State

    Empty State

    775
  • Balloons

    Balloons

    755
  • Status Badge

    Status Badge

    646