A common requirement in search inputs is debouncing.
Debouncing delays execution until the user stops typing for a defined
interval. This prevents unnecessary calls such as repeated API requests.

This example demonstrates how to implement debounced search in a React
functional component
using:

  • useState
  • useRef
  • useEffect
  • lodash/debounce

Key Idea

Create a debounced version of the search function once, then trigger it
whenever the input state changes.

useRef stores the debounced function so it persists across renders.


Implementation

import React, { useRef, useEffect, useState } from "react";
import debounce from "lodash/debounce";

const MyComponent = () => {
  const [searchTerm, setSearchTerm] = useState("");

  const debouncedSearch = useRef(
    debounce((term) => {
      performSearch(term);
    }, 500)
  ).current;

  useEffect(() => {
    debouncedSearch(searchTerm);
  }, [searchTerm]);

  function onSearchChange(event) {
    setSearchTerm(event.target.value);
  }

  function performSearch(term) {
    // Execute search logic here
  }

  return (
    <input
      type="text"
      value={searchTerm}
      onChange={onSearchChange}
    />
  );
};

export default MyComponent;

How It Works

1. Store Input State

useState stores the current search input.

const [searchTerm, setSearchTerm] = useState("");

2. Create a Debounced Function

useRef ensures the debounced function is created once and reused
across renders.

const debouncedSearch = useRef(
  debounce((term) => performSearch(term), 500)
).current;

Delay: 500 ms

3. Trigger Search on Input Change

useEffect calls the debounced function whenever searchTerm changes.

useEffect(() => {
  debouncedSearch(searchTerm);
}, [searchTerm]);

4. Update Input Value

The input handler updates the state.

function onSearchChange(event) {
  setSearchTerm(event.target.value);
}

Result

Behavior:

  • User types into the input
  • searchTerm updates immediately
  • The search function runs only after the user stops typing for 500
    ms

Benefits:

  • Fewer API calls
  • Reduced UI jitter
  • Improved performance