React: Debouncing input with useEffect

React: Debouncing input with useEffect

Debouncing is a technique that ensures a function is only called after a certain period of time has passed since the last event. It’s often used in cases like search inputs, where you don’t want to make an API call on every keystroke but only after the user has finished typing.

Example: Debouncing a Search Input

Let’s say you have a search input that makes an API call. Without debouncing, it would make an API call for every keystroke, which is inefficient. Here’s how you can debounce it using useEffect:

import React, { useState, useEffect } from "react";

const DebouncedSearch = () => {
  const [query, setQuery] = useState("");  // The search query typed by user
  const [debouncedQuery, setDebouncedQuery] = useState(query);  // Debounced value

  useEffect(() => {
    // Set a timeout to update debounced value after 500ms
    const handler = setTimeout(() => {
      setDebouncedQuery(query);
    }, 500);

    // Cleanup the timeout if `query` changes before 500ms
    return () => {
      clearTimeout(handler);
    };
  }, [query]);

  // Whenever debouncedQuery changes, simulate an API call
  useEffect(() => {
    if (debouncedQuery) {
      console.log("API call with query:", debouncedQuery);
      // Make API call here
    }
  }, [debouncedQuery]);

  return (
    <div>
      <input
        type="text"
        placeholder="Search..."
        value={query}
        onChange={(e) => setQuery(e.target.value)}
      />
      <p>Debounced Query: {debouncedQuery}</p>
    </div>
  );
};

export default DebouncedSearch;

How it works:

  1. State: query stores the immediate input value, and debouncedQuery stores the value after the debounce period.

  2. useEffect (Debounce): When query changes, a timeout is set for 500ms. If the user stops typing, the debouncedQuery is updated after 500ms. If the user types again before 500ms, the timeout is cleared, and a new one is set.

  3. useEffect (API call): Once the debouncedQuery is updated, we can simulate the API call.

This way, you only trigger the API call when the user finishes typing, improving performance and avoiding unnecessary requests.

Key takeaway: Using debouncing in input-heavy components keeps them efficient and responsive without making too many API calls or expensive operations.