Building a Complete Search Autocomplete Feature in React

Autocomplete search is a common feature in modern applications. It helps users quickly find what they need by showing suggestions while they type. In this article, we will walk through the full implementation of an autocomplete component built with React. We will explain each line of code, every state variable, and the logic behind the behavior.

We will work with two components:

  1. SearchAutocomplete — the main logic (fetching data, filtering, handling input)
  2. Suggestions — a presentation component that displays the suggestion list

Let’s go through the functionality in depth.

SEE THE FULL CODE IN GITHUB

The SearchAutocomplete Component

import { useEffect, useState } from 'react'
import Suggestions from './suggestions'

We import two important React hooks:

  • useState → used to store and update values inside the component
  • useEffect → used to run code when the component mounts
    We also import the Suggestions component that we will use later.

Declaring All State Variables

const [loading, setLoading] = useState(false)
const [users, setUsers] = useState([])
const [error, setError] = useState(null)
const [searchParam, setSearchParam] = useState('')
const [showDropdown, setShowDropdown] = useState(false)
const [filteredUsers, setFilteredUsers] = useState([])

Each state variable has a specific purpose:

loading

  • Starts as false
  • Becomes true while data is being fetched from the API
  • Helps us display a loading message

users

  • Will store the list of all user first names fetched from the remote API

error

  • Stores any error that occurs during the API request
  • Helps us display an error message

searchParam

  • Stores the text typed inside the search input
  • Makes the input a controlled input

showDropdown

  • Controls whether the suggestions dropdown is visible
  • Becomes true only when the user types more than 1 character

filteredUsers

  • Stores the users that match the search text
  • This list is displayed inside the dropdown

These state variables together allow us to handle:

  • User input
  • API data
  • UI visibility
  • Error handling

The Input Change Handler

function handleChange(event) {
const query = event.target.value.toLowerCase()
setSearchParam(query)

if (query.length > 1) {
const filteredData =
users && users.length
? users.filter(item => item.toLowerCase().indexOf(query) > -1)
: []
setFilteredUsers(filteredData)
setShowDropdown(true)
} else {
setShowDropdown(false)
}
}

This function runs every time the user types in the input field.

Let’s break down each step:

Step 1: Read the Input Value

const query = event.target.value.toLowerCase()

We convert it to lowercase to allow case-insensitive search.

Step 2: Update the searchParam

setSearchParam(query)

This makes the input controlled by React.

Step 3: Only search if the user typed more than 1 character

if (query.length > 1) {

This prevents showing suggestions for short input like “a”.

Step 4: Filter the User List

const filteredData = users.filter(item =>
item.toLowerCase().indexOf(query) > -1
)

Here is how the filtering works:

  • Convert each username to lowercase
  • Check if the typed text exists inside the username
  • Keep only the matching names

Step 5: Update States

setFilteredUsers(filteredData)
setShowDropdown(true)

Step 6: Hide Suggestions if the Input Is Too Short

else {
setShowDropdown(false)
}

Handling Click on a Suggestion

function handleClick(event) {
setShowDropdown(false);
setSearchParam(event.target.innerText);
setFilteredUsers([]);
}

When the user clicks a name:

  1. Close the dropdown
  2. Put the clicked name into the input field
  3. Clear the list of suggestions

This gives the effect of selecting a suggestion and confirming the value.

Fetching Users from the API

async function fetchListOfUsers () {
try {
setLoading(true)
const response = await fetch('https://dummyjson.com/users')
const data = await response.json()
if (data && data.users && data.users.length) {
setUsers(data.users.map(userItem => userItem.firstName))
setLoading(false)
setError(null)
}
} catch (error) {
setLoading(false)
setError(error)
}
}

1. Set loading to true

setLoading(true)

2. Fetch user data

const response = await fetch('https://dummyjson.com/users')
const data = await response.json()

3. Store the first names only

setUsers(data.users.map(userItem => userItem.firstName))

4. Reset loading and error states

setLoading(false)
setError(null)

5. Error handling

If something goes wrong, store the error and stop loading.

Running the API Call with useEffect

useEffect(() => {
fetchListOfUsers()
}, [])
  • Runs once when the component first loads
  • Works like a componentDidMount in class components

This ensures the API call runs only one time.

Rendering the UI

if(error){
return <h1>Error</h1>;
}

If something went wrong, show an error message.

Main Render Section

<div className='search-autocomplete-container'>
{loading ? (
<h1>Loading Data. Please wait</h1>
) : (
<input
value={searchParam}
name='search-users'
placeholder='Search Users here...'
onChange={handleChange}
/>
)}

What this does:

  • If data is still loading → show “Loading Data”
  • Otherwise → show the input field

Showing the Suggestions

{showDropdown && <Suggestions handleClick={handleClick} data={filteredUsers} />}

This line:

  • Only shows the dropdown if showDropdown is true
  • Passes the list of filtered users
  • Passes the click handler

The Suggestions Component

export default function Suggestions ({ data, handleClick }) {
return (
<ul>
{data && data.length
? data.map((item, index) => (
<li key={index} onClick={handleClick}>
{item}
</li>
))
: null}
</ul>
)
}

This component is simple:

  • Receives the filtered users
  • Displays each one in a <li>
  • Calls handleClick when clicked

It is a pure UI component with no logic.

Final Result

With both components combined, we now have:

  • A working autocomplete feature
  • Real user data from an API
  • Controlled input
  • Case-insensitive filtering
  • A dropdown that hides or shows based on input
  • Click-to-select behavior

The component is clean, efficient, and easy to extend.

SEE THE FULL CODE IN GITHUB

Happy coding !!


Building a Complete Search Autocomplete Feature in React was originally published in Javarevisited on Medium, where people are continuing the conversation by highlighting and responding to this story.

This post first appeared on Read More