Building an Auto Complete Search Bar Component in React

Here is a step-by-step breakdown and explanation of how you built the Autocomplete Search Bar in React, including key concepts like debouncing, caching, API calls, and conditional rendering.

✅ Objective

You built a live autocomplete search bar that:

  • Fetches suggestions from an API as the user types.
  • Uses debouncing to avoid too many API calls.
  • Caches results to improve performance.
  • Displays suggestions dynamically in a dropdown.

✅ 1. Initial Setup and State Management

✅ States used:

const [result, setResult] = useState([]);      // Search results from API
const [search, setSearch] = useState("");      // Current search input
const [open, setOpen] = useState(false);       // Controls visibility of suggestion box
const [cache, setCahce] = useState({});        // Stores previously fetched results

✅ 2. Fetching Data with Debouncing

✅ fetchData() logic:

const fetchData = async () => {
  if (cache[search]) {
    setResult(cache[search]);                 // Use cached result
    console.log("Cache return ", search);
    return;
  }

  const data = await fetch(
    "https://dummyjson.com/recipes/search?q=" + search
  );
  const json = await data.json();

  console.log("API call ", search);
  setResult(json?.recipes);
  setCahce((prev) => ({ ...prev, [search]: json?.recipes }));
};
  • If the result exists in cache, reuse it.
  • Else, fetch from the API and store the result in both result and cache.

✅ 3. Debounce API Call using useEffect

useEffect(() => {
  const timer = setTimeout(() => fetchData(), 300);

  return () => clearTimeout(timer); // Cleanup on re-render or unmount
}, [search]);

💡 Why Debounce?

  • Prevents unnecessary API calls on every keystroke.
  • Waits for 300ms after the user stops typing before calling the API.

✅ 4. Input Box UI and Interaction

<input
  type="text"
  className="input_box"
  value={search}
  onChange={(e) => setSearch(e.target.value)}
  onFocus={() => setOpen(true)}
  onBlur={() => setOpen(false)}
/>

✅ Features:

  • Controlled input with search state.
  • Opens dropdown on focus.
  • Hides dropdown on blur.

✅ 5. Conditional Rendering of Suggestions

{search && open && (
  <ul className="result-box">
    {result.map((val) => (
      <li className="result" key={val.id}>
        {val.name}
      </li>
    ))}
  </ul>
)}

✅ Logic:

  • Render suggestions only if:
    • search is non-empty
    • Input is focused (open === true)
  • Maps result array and displays each name as a list item.

✅ 6. Complete Code Recap

export default function App() {
  const [result, setResult] = useState([]);
  const [search, setSearch] = useState("");
  const [open, setOpen] = useState(false);
  const [cache, setCahce] = useState({});

  const fetchData = async () => {
    if (cache[search]) {
      setResult(cache[search]);
      return;
    }
    const data = await fetch("https://dummyjson.com/recipes/search?q=" + search);
    const json = await data.json();
    setResult(json?.recipes);
    setCahce((prev) => ({ ...prev, [search]: json?.recipes }));
  };

  useEffect(() => {
    const timer = setTimeout(() => fetchData(), 300);
    return () => clearTimeout(timer);
  }, [search]);

  return (
    <div className="App">
      <h1>Machine Coding Round</h1>
      <h2>Autocomplete Search Bar</h2>

      <input
        type="text"
        className="input_box"
        value={search}
        onChange={(e) => setSearch(e.target.value)}
        onFocus={() => setOpen(true)}
        onBlur={() => setOpen(false)}
      />

      {search && open && (
        <ul className="result-box">
          {result.map((val) => (
            <li className="result" key={val.id}>
              {val.name}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

✅ Extra Ideas to Enhance It

  • Highlight matching keywords in suggestions
  • Add keyboard navigation (arrow keys to select).
  • Add loading spinner while fetching data.
  • Show No results found if result.length === 0.
  • Provides a smooth user experience like most OTP inputs on modern apps