Introduction
Autocomplete is a feature in which an input field suggests a word based on user input. This helps improve the user experience in your application, such as cases where a search is necessary.
In this article, you will examine how to build an autocomplete component in React. You will work with a fixed list of suggestions, event binding, understanding keyboard codes, and operate state management.
Prerequisites
To complete this tutorial, you will need the following:
An understanding of React is required. To learn more about React, check out the How To Code in React series.
Step 1 — Building Your Autocomplete
Component
The Autocomplete
component is where you will craft the functionality in the autocomplete feature.
Create an Autocomplete.js
file, and import React and instantiate an Autocomplete
class:
Autocomplete.js
import React, { Component, Fragment } from "react";
import './styles.css'
class Autocomplete extends Component {
constructor(props) {
super(props);
this.state = {
activeSuggestion: 0,
filteredSuggestions: [],
showSuggestions: false,
userInput: ""
};
}
On your state, the activeSuggestion
property defines the index of a selected suggestion. The property filteredSuggestions
, set to an empty array, matches the user’s input. The showSuggestions
property will determine whether or not the the suggestion list appears, and the userInput
property assigns itself an empty string for accepting a word from a user’s input.
With your class started and state set, let’s look at the methods to apply in the component.
In your Autocomplete.js
file, define an onChange
method and update your state:
Autocomplete.js
onChange = e => {
const { suggestions } = this.props;
const userInput = e.currentTarget.value;
const filteredSuggestions = suggestions.filter(
suggestion =>
suggestion.toLowerCase().indexOf(userInput.toLowerCase()) > -1
);
this.setState({
activeSuggestion: 0,
filteredSuggestions,
showSuggestions: true,
userInput: e.currentTarget.value
});
};
The method onChange
will fire when the user changes the input value. On each change, the method will filter into the suggestion list and return suggestions that do not contain the user’s input. Once the filter runs through, the .setState()
method will revise your state’s userInput
property to contain a value, set your showSuggestions
boolean to allow suggestions to show, and reset the activeSuggestion
property on each method call.
The onClick
event will invoke when the user clicks on a suggestion. In your Autocomplete.js
file, declare an onClick
method and implement a .setState()
method:
Autocomplete.js
onClick = e => {
this.setState({
activeSuggestion: 0,
filteredSuggestions: [],
showSuggestions: false,
userInput: e.currentTarget.innerText
});
};
The .setState()
method will update the user’s input and reset your state’s properties.
The onKeyDown
method will engage when the user presses a key down. In your Autocomplete.js
file, declare an onKeyDown
method and set several conditionals:
Autocomplete.js
onKeyDown = e => {
const { activeSuggestion, filteredSuggestions } = this.state;
if (e.keyCode === 13) {
this.setState({
activeSuggestion: 0,
showSuggestions: false,
userInput: filteredSuggestions[activeSuggestion]
});
} else if (e.keyCode === 38) {
if (activeSuggestion === 0) {
return;
}
this.setState({ activeSuggestion: activeSuggestion - 1 });
}
// User pressed the down arrow, increment the index
else if (e.keyCode === 40) {
if (activeSuggestion - 1 === filteredSuggestions.length) {
return;
}
this.setState({ activeSuggestion: activeSuggestion + 1 });
}
};
Once you’ve stored your properties activeSuggestion
and filteredSuggestion
in a deconstructed object, the conditionals will check if the key the user pressed down matches the key codes. The first conditional will check if the key code matches 13
, the enter key, and run the .setState()
method to update the userInput
property and close the suggestions list. If the user pressed the up arrow, the key code 38
, the conditional will decrement the index of the activeSuggestion
property, and return nothing if the index is zero. If the user pressed the down arrow, the key code 40
, the conditional will increment the index in the activeSuggestion
property, and return nothing if the index matches the length of the filteredSuggestions
property.
With your methods now complete, let’s navigate to applying your render
lifecycle method.
In your Autocomplete.js
file, set a render()
statement, and define your methods and state in a deconstructed object:
Autocomplete.js
render() {
const {
onChange,
onClick,
onKeyDown,
state: {
activeSuggestion,
filteredSuggestions,
showSuggestions,
userInput
}
} = this;
let suggestionsListComponent;
The variable suggestionsListComponent
has no defined value as you will assign them in the conditionals below:
Autocomplete.js
if (showSuggestions && userInput) {
if (filteredSuggestions.length) {
suggestionsListComponent = (
<ul class="suggestions">
{filteredSuggestions.map((suggestion, index) => {
let className;
// Flag the active suggestion with a class
if (index === activeSuggestion) {
className = "suggestion-active";
}
return (
<li className={className} key={suggestion} onClick={onClick}>
{suggestion}
</li>
);
})}
</ul>
);
} else {
suggestionsListComponent = (
<div class="no-suggestions">
<em>No suggestions available.</em>
</div>
);
}
}
The first conditional will check if the values on the properties showSuggestions
and userInput
exists, while the following condition will check for the length of the filteredSuggestions
property. If the conditionals are met, the suggestionsListComponent
variable assigns itself the value of iterating through the filteredSuggestions
property and flag an active suggestion with a class name if the index matches the value in the activeSuggestion
property. The suggestionsListComponent
variable will return an ordered list of the suggestions upon execution of the onClick
method, and assign each suggestion a class name. If the values on the properties showSuggestions
and userInput
do not exist, a text will appear to indicate no there are no suggestions available.
If the user does not meet the conditions listed, the render()
lifecycle method will return a React Fragment
to apply the input field and invoke the methods without adding extra nodes to the document object model:
Autocomplete.js
return (
<Fragment>
<input
type="text"
onChange={onChange}
onKeyDown={onKeyDown}
value={userInput}
/>
{suggestionsListComponent}
</Fragment>
);
}
}
export default Autocomplete;
Now that you’ve developed your Autocomplete
component, export the file combine its functionality in another component.
Step 2 — Joining Your React Project
The App
component is where you will display the functionality in your Autocomplete
component. In your index.js
file, declare an App
component and import your Autocomplete
component:
index.js
import React from "react";
import Autocomplete from "./Autocomplete";
function App() {
return (
<div>
<h1>React Autocomplete Demo</h1>
<h2>Start typing and experience the autocomplete wizardry!</h2>
<Autocomplete suggestions={"Oranges", "Apples", "Banana", "Kiwi", "Mango"]}/>
</div>
);
}
export default App
The return statement in your App
component accepts the Autocomplete
component with the fixed list of suggestions.
Step 3 — Styling Your Autocomplete
Component
To finish your Autocomplete
component, add styling with CSS to position and color your application and input field.
Create a styles.css
file and set CSS rules to shape your Autocomplete
component:
styles.css
body {
font-family: sans-serif;
}
input {
border: 1px solid #999;
padding: 0.5rem;
width: 300px;
}
.no-suggestions {
color: #999;
padding: 0.5rem;
}
.suggestions {
border: 1px solid #999;
border-top-width: 0;
list-style: none;
margin-top: 0;
max-height: 143px;
overflow-y: auto;
padding-left: 0;
width: calc(300px + 1rem);
}
.suggestions li {
padding: 0.5rem;
}
.suggestion-active,
.suggestions li:hover {
background-color: #008f68;
color: #fae042;
cursor: pointer;
font-weight: 700;
}
.suggestions li:not(:last-of-type) {
border-bottom: 1px solid #999;
}
With your CSS rules constructed, import the file into your Autocomplete.js
file to apply your styles.
Conclusion
React offers measures to construct the autocomplete functionality available in one component with built-in and custom methods to interact with the user.
Check out how the Autocomplete component operates in CodeSandbox.