Part 39: Debouncing & Throttling: Optimizing User Input & Search

Part 39 Technology Updated September 12, 2026

Part 39: Debouncing & Throttling: Optimizing User Input & Search

When a user types into a live search box, firing an API request on every keystroke can overwhelm backend servers and create race conditions.


1. Debounce vs. Throttle

  • Debounce: Delays execution until a specified quiet period has elapsed after the last event. (Ideal for search inputs and auto-saving).
  • Throttle: Guarantees execution at most once per specified time interval. (Ideal for scroll listeners, window resizing, and mouse movement).

2. Creating a Reusable useDebounce Hook

import { useState, useEffect } from 'react';

export function useDebounce(value, delay = 300) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    // Cancel timer if value changes before delay finishes
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

3. Real-World Live Search Component

import { useState, useEffect } from 'react';
import { useDebounce } from './useDebounce';

export default function SearchAutocomplete() {
  const [searchTerm, setSearchTerm] = useState('');
  const debouncedSearch = useDebounce(searchTerm, 400);
  const [results, setResults] = useState([]);

  useEffect(() => {
    if (!debouncedSearch.trim()) {
      setResults([]);
      return;
    }

    async function searchApi() {
      const res = await fetch(`/api/search?q=${encodeURIComponent(debouncedSearch)}`);
      const data = await res.json();
      setResults(data);
    }

    searchApi();
  }, [debouncedSearch]);

  return (
    <div>
      <input
        type="text"
        value={searchTerm}
        onChange={(e) => setSearchTerm(e.target.value)}
        placeholder="Type to search..."
        className="border p-2 rounded w-full"
      />
      <ul>
        {results.map(item => <li key={item.id}>{item.name}</li>)}
      </ul>
    </div>
  );
}

Key Takeaways

  • Debounce search inputs to prevent server overload and race conditions.
  • Implement useDebounce with setTimeout and cleanup via clearTimeout.

In Part 40, we enter Module 7 to explore Code Splitting with React.lazy and Suspense!