Table of contents
1.
Introduction
2.
Setting Up the React Environment
3.
Understanding the Basics of React Autocomplete Component
4.
Designing the Autocomplete Component Structure
5.
Creating the Autocomplete Functionality
6.
Managing User Input and Component State
7.
Rendering Suggestions and Handling Selection  
8.
Enhancing User Experience with ARIA Attributes
9.
Styling the Autocomplete Component with CSS
10.
Integrating the Autocomplete Component in a React App  
10.1.
Step 1: Setting Up the React App  
10.2.
Step 2: Adding the Autocomplete Component  
10.3.
Step 3: Testing the Integration  
10.4.
Step 4: Customizing the Component  
11.
Handling Edge Cases and Adding Advanced Features
11.1.
Handling No Matches
11.2.
Keyboard Navigation
12.
Testing and Debugging the Autocomplete Component  
12.1.
Step 1: Testing the Basic Functionality  
12.2.
Step 2: Handling Edge Cases  
12.3.
Step 3: Debugging Common Issues  
12.4.
Step 4: Enhancing the User Experience  
13.
Best Practices and Performance Considerations
14.
Frequently Asked Questions
14.1.
How do I optimize performance in an autocomplete component?
14.2.
How can I handle case-sensitive searches?
14.3.
Can I fetch autocomplete suggestions from an API?
15.
Conclusion
Last Updated: Feb 12, 2025
Medium

How To Build an Autocomplete Component in React JS

Author Sinki Kumari
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

An autocomplete component in React.js helps users find and select suggestions while typing in an input field. It enhances user experience by providing real-time search suggestions, commonly used in search bars and forms. React allows building this feature using state management and API calls for dynamic results.

How To Build an Autocomplete Component in React JS

In this article, we will learn how to build an autocomplete component in React JS. We will discuss setting up the environment, managing state, handling user input, and improving performance with best practices.

Setting Up the React Environment

Before creating an autocomplete component, you need to set up a React environment. Follow these steps:

  1. Install Node.js and npm.
     

Create a React app using the command:

npx create-react-app autocomplete-app

 

Navigate to the project folder:

cd autocomplete-app


Start the development server:

npm start

Now, you are ready to build the autocomplete component.

Understanding the Basics of React Autocomplete Component

An autocomplete component consists of an input field and a dropdown list displaying suggestions. When users type in the input field, it filters and displays matching options.

Designing the Autocomplete Component Structure

Create a new file Autocomplete.js and define the basic structure:

import React, { useState } from 'react';

const Autocomplete = ({ suggestions }) => {
  const [input, setInput] = useState('');
  const [filteredSuggestions, setFilteredSuggestions] = useState([]);

  return (
    <div>
      <input
        type="text"
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="Type to search..."
      />
      <ul>
        {filteredSuggestions.map((suggestion, index) => (
          <li key={index}>{suggestion}</li>
        ))}
      </ul>
    </div>
  );
};

export default Autocomplete;

 

This structure includes an input field and a list to display suggestions.

Creating the Autocomplete Functionality

Modify the onChange function to filter suggestions:

const handleChange = (e) => {
  const value = e.target.value;
  setInput(value);

  if (value) {
    const filtered = suggestions.filter((suggestion) =>
      suggestion.toLowerCase().includes(value.toLowerCase())
    );
    setFilteredSuggestions(filtered);
  } else {
    setFilteredSuggestions([]);
  }
};

 

Now, the component dynamically filters suggestions based on user input.

Managing User Input and Component State

React state management ensures the input field and suggestion list are updated correctly:

const [input, setInput] = useState('');
const [filteredSuggestions, setFilteredSuggestions] = useState([]);

 

These states store user input and the filtered suggestion list.

Rendering Suggestions and Handling Selection  

When building an autocomplete feature, rendering suggestions is one of the most important steps. This involves showing a list of options to the user based on what they have typed so far. To achieve this in React JS, we need to manage the input value, filter the data, & display matching results dynamically. Let’s break this process into smaller steps.  

First, we need an array of data that will act as the source for our suggestions. For example, let’s assume we have a list of programming languages like JavaScript, Python, Java, C++, etc. We will use this list to filter suggestions based on the user’s input.  

Next, we create a state to store the user’s input & another state to hold the filtered suggestions. Using React’s `useState` hook, we can easily manage these values. This is how the code looks:  

import React, { useState } from 'react';  
function Autocomplete() {  
  const [inputValue, setInputValue] = useState('');  
  const [suggestions, setSuggestions] = useState([]);  
  const languages = ['JavaScript', 'Python', 'Java', 'C++', 'Ruby', 'Go', 'Kotlin'];  
  const handleInputChange = (e) => {  
    const value = e.target.value;  
    setInputValue(value);  


    // Filter the suggestions based on user input  
    if (value.trim() === '') {  
      setSuggestions([]);  
    } else {  
      const filtered = languages.filter((lang) =>  
        lang.toLowerCase().includes(value.toLowerCase())  
      );  
      setSuggestions(filtered);  
    }  
  };  
  return (  
    <div>  
      <input  
        type="text"  
        value={inputValue}  
        onChange={handleInputChange}  
        placeholder="Type a programming language..."  
      />  
      <ul>  
        {suggestions.map((suggestion, index) => (  
          <li key={index}>{suggestion}</li>  
        ))}  
      </ul>  
    </div>  
  );  
}  
export default Autocomplete;  


In the above code, we first imported React & the `useState` hook. We created two states: `inputValue` to track what the user types & `suggestions` to store the filtered results. The `languages` array acts as our data source. When the user types in the input box, the `handleInputChange` function filters the array & updates the suggestions.  
 

The suggestions are displayed in an unordered list (`<ul>`), where each suggestion is rendered as a list item (`<li>`). If the input is empty, no suggestions are shown.  

Now, let’s talk about handling selection. When a user clicks on a suggestion, we want to update the input field with the selected value & clear the suggestions. To do this, we add a click event handler to each suggestion. Let’s take a look at the updated code:  

const handleSuggestionClick = (selectedValue) => {  
  setInputValue(selectedValue);  
  setSuggestions([]);  
};  

return (  
  <div>  
    <input  
      type="text"  
      value={inputValue}  
      onChange={handleInputChange}  
      placeholder="Type a programming language..."  
    />  
    <ul>  
      {suggestions.map((suggestion, index) => (  
        <li key={index} onClick={() => handleSuggestionClick(suggestion)}>  
          {suggestion}  
        </li>  
      ))}  
    </ul>  
  </div>  
);  


In this updated version, the `handleSuggestionClick` function sets the input value to the clicked suggestion & clears the suggestions list. Each suggestion now has an `onClick` event that triggers this function.  

This approach ensures that the suggestions are rendered dynamically & user selections are handled properly.  

Enhancing User Experience with ARIA Attributes

Adding ARIA attributes improves accessibility:

<input
  type="text"
  aria-autocomplete="list"
  aria-controls="suggestions-list"
  value={input}
  onChange={handleChange}
/>
<ul id="suggestions-list">

 

This ensures screen readers can interpret the autocomplete functionality.

Styling the Autocomplete Component with CSS

Create Autocomplete.css to enhance UI:

ul {
  list-style: none;
  padding: 0;
  border: 1px solid #ccc;
  max-height: 150px;
  overflow-y: auto;
}
li {
  padding: 8px;
  cursor: pointer;
}
li:hover {
  background-color: #f0f0f0;
}


Import this file in Autocomplete.js:

import './Autocomplete.css';

Integrating the Autocomplete Component in a React App  

Once we have built the autocomplete component, the next step is to integrate it into a React app. This involves adding the component to your project structure & ensuring it works seamlessly with other parts of the application. Let’s understand this process step by step.  

Step 1: Setting Up the React App  

If you don’t already have a React app, you can create one using `create-react-app`. Open your terminal & run the following command:  

npx create-react-app autocomplete-app  
cd autocomplete-app  


This will set up a new React project. Once the setup is complete, you can start the development server by running:  

npm start  


Your app should now be running on `http://localhost:3000`.  

Step 2: Adding the Autocomplete Component  

Now that the app is ready, let’s add the autocomplete component we built earlier. Create a new file called `Autocomplete.js` in the `src` folder & paste the complete code from the previous section into it.  

Next, open the `App.js` file in the `src` folder & import the `Autocomplete` component. Let’s see how the updated `App.js` file should look:  

import React from 'react';  
import Autocomplete from './Autocomplete';  
function App() {  
  return (  
    <div className="App" style={{ padding: '20px' }}>  
      <h1>Autocomplete Example</h1>  
      <Autocomplete />  
    </div>  
  );  
}  


export default App;  


In this code, we imported the `Autocomplete` component & rendered it inside the `App` component. We also added some basic styling using inline CSS to make the app look cleaner.  

Step 3: Testing the Integration  

After saving the changes, your React app should automatically reload in the browser. You should see the autocomplete input box with the heading "Autocomplete Example". Try typing in the input box & observe how the suggestions appear dynamically. Clicking on a suggestion should update the input field with the selected value.  

Step 4: Customizing the Component  

To make the autocomplete component more reusable, you can pass the data source as a prop. For example, instead of hardcoding the `languages` array inside the component, you can pass it from the parent component. Here’s how you can modify the `Autocomplete` component to accept props:  

function Autocomplete({ data }) {  
  const [inputValue, setInputValue] = useState('');  
  const [suggestions, setSuggestions] = useState([]);  
  const handleInputChange = (e) => {  
    const value = e.target.value;  
    setInputValue(value);  
    if (value.trim() === '') {  
      setSuggestions([]);  
    } else {  
      const filtered = data.filter((item) =>  
        item.toLowerCase().includes(value.toLowerCase())  
      );  
      setSuggestions(filtered);  
    }  
  };  
  const handleSuggestionClick = (selectedValue) => {  
    setInputValue(selectedValue);  
    setSuggestions([]);  
  };  

  return (  
    <div>  
      <input  
        type="text"  
        value={inputValue}  
        onChange={handleInputChange}  
        placeholder="Start typing..."  
      />  
      <ul>  
        {suggestions.map((suggestion, index) => (  
          <li key={index} onClick={() => handleSuggestionClick(suggestion)}>  
            {suggestion}  
          </li>  
        ))}  
      </ul>  
    </div>  
  );  
}  


Now, update the `App.js` file to pass the data as a prop:  

function App() {  
  const languages = ['JavaScript', 'Python', 'Java', 'C++', 'Ruby', 'Go', 'Kotlin'];  
  return (  
    <div className="App" style={{ padding: '20px' }}>  
      <h1>Autocomplete Example</h1>  
      <Autocomplete data={languages} />  
    </div>  
  );  
}  


This approach makes the component more flexible & allows you to use it with different datasets.  

Handling Edge Cases and Adding Advanced Features

Handling No Matches

Display a message when no matches are found:

{filteredSuggestions.length === 0 && input && <p>No suggestions found</p>}

Keyboard Navigation

Allow users to navigate using arrow keys:

const handleKeyDown = (e) => {
  if (e.key === 'ArrowDown') {
    // Move selection down
  } else if (e.key === 'ArrowUp') {
    // Move selection up
  }
};

 

Attach handleKeyDown to the input field.

Testing and Debugging the Autocomplete Component  

Once the autocomplete component is integrated into the React app, it’s crucial to test & debug it thoroughly. This ensures that the feature works as expected & handles edge cases effectively. Let’s discuss how to test the component & address common issues that might arise during development.  

Step 1: Testing the Basic Functionality  

The first step is to verify that the basic functionality works. Open your app in the browser & perform the following tests:  

1. Empty Input: Ensure no suggestions are displayed when the input field is empty.  
 

2. Matching Suggestions: Type a few characters & confirm that the suggestions match the input. For example, typing "Py" should show "Python".  
 

3. No Matches: Type something that doesn’t match any item in the dataset (e.g., "XYZ") & ensure no suggestions are shown.  
 

4. Selection: Click on a suggestion & check if the input field updates correctly.  


These tests help confirm that the core logic of filtering & rendering suggestions is working properly.  

Step 2: Handling Edge Cases  

Edge cases are scenarios that might not occur frequently but can cause issues if not handled. Let’s take a look at some examples & how to solve them:  

1. Case Sensitivity: Ensure the filtering logic is case-insensitive. For instance, typing "java" should match "Java". This is already handled in our code using `toLowerCase()`.  
 

2. Whitespace: If the user types spaces before or after the input, the suggestions should still work. You can trim the input value using `trim()` in the `handleInputChange` function.  


Here’s the updated `handleInputChange` function with trimming:  

const handleInputChange = (e) => {  
  const value = e.target.value.trim(); // Trim whitespace  
  setInputValue(value);  

  if (value === '') {  
    setSuggestions([]);  
  } else {  
    const filtered = data.filter((item) =>  
      item.toLowerCase().includes(value.toLowerCase())  
    );  
    setSuggestions(filtered);  
  }  
};  


3. Duplicate Suggestions: Ensure there are no duplicate items in the dataset. If duplicates exist, they will appear multiple times in the suggestions list. You can use a `Set` to remove duplicates from the dataset before filtering.  

Step 3: Debugging Common Issues  

If something isn’t working as expected, here are a few debugging tips:  


1. Console Logs: Use `console.log()` to inspect the values of variables like `inputValue`, `suggestions`, & `data`. For example:  

  console.log('Input Value:', inputValue);  @   console.log('Filtered Suggestions:', suggestions); 


2. React DevTools: Use the React Developer Tools browser extension to inspect the component’s state & props. This helps identify issues with state management.  


3. Error Messages: Pay attention to error messages in the browser console. They often provide clues about what went wrong.  

Step 4: Enhancing the User Experience  

To make the autocomplete feature more robust, consider adding the following improvements:  

1. Highlighting Matches: Highlight the matching part of the suggestion in bold. For example, if the user types "Py", the suggestion "Python" should display "Python".  


Let’s see how you can implement this:  

const highlightMatch = (text, query) => {  
const index = text.toLowerCase().indexOf(query.toLowerCase());  
if (index === -1) return text;  
     return (  
       <>  
         {text.substring(0, index)}  
         <strong>{text.substring(index, index + query.length)}</strong>  
         {text.substring(index + query.length)}  
       </>  
     );  
   };  


Update the rendering logic to use this function:  

<li key={index} onClick={() => handleSuggestionClick(suggestion)}>  
     {highlightMatch(suggestion, inputValue)}  
</li>  


2. Keyboard Navigation: Allow users to navigate through suggestions using the arrow keys & select an option using the Enter key. This requires adding event listeners for `keydown` events.  

Best Practices and Performance Considerations

  • Use memoization to optimize rendering.
     
  • Limit suggestions to prevent performance issues.
     

Debounce input changes for better efficiency:

import { useEffect } from 'react';
useEffect(() => {
  const timeout = setTimeout(() => {
    // Fetch or filter data
  }, 300);
  return () => clearTimeout(timeout);
}, [input]);

Frequently Asked Questions

How do I optimize performance in an autocomplete component?

Use memoization, limit the number of suggestions, and implement debouncing.

How can I handle case-sensitive searches?

Convert both user input and suggestions to lowercase before filtering.

Can I fetch autocomplete suggestions from an API?

Yes, use fetch or axios to get suggestions dynamically from an API.

Conclusion

In this article, we built an autocomplete component in React JS from scratch. We covered state management, filtering suggestions, handling user input, accessibility enhancements, styling, and best practices. By implementing these techniques, we can create a responsive and efficient autocomplete feature for our React applications.

Live masterclass