react-autocomplete, react-autosuggest, and react-select are React libraries that provide user input components with suggestions or options. They help developers build accessible, customizable dropdowns or type-ahead fields for forms, search interfaces, and data entry. While all three enable users to select from a list of options, they differ significantly in architecture, flexibility, built-in features, and use-case focus.
When you need to let users pick from a dynamic list of options — whether it’s a country selector, a tag input, or a product search — you’ll likely reach for a library. The three packages under review (react-autocomplete, react-autosuggest, and react-select) all aim to solve this problem, but they take very different approaches. Let’s compare them through the lens of real-world development needs.
Before diving into features, it’s critical to address maintenance:
react-autocomplete is officially deprecated. The npm page states: "This package is no longer maintained. Please use react-autosuggest instead." It hasn’t seen meaningful updates in years and lacks modern accessibility standards (like ARIA compliance) and TypeScript support. Do not use it in new projects.
react-autosuggest and react-select are both actively maintained, with regular releases and responsive issue tracking on GitHub.
Given this, the practical comparison is really between react-autosuggest and react-select — but we’ll still show react-autocomplete examples for completeness in legacy contexts.
react-autocomplete: Minimalist (Deprecated)This library provides a barebones wrapper around an input and a suggestion list. You manage nearly everything: filtering, selection, styling, and keyboard behavior.
// react-autocomplete (deprecated)
import Autocomplete from 'react-autocomplete';
<Autocomplete
items={items}
getItemValue={(item) => item.label}
renderItem={(item, isHighlighted) => (
<div style={{ background: isHighlighted ? 'lightgray' : 'white' }}>
{item.label}
</div>
)}
value={value}
onChange={(e) => setValue(e.target.value)}
onSelect={(val) => setValue(val)}
/>
It works, but you’re on your own for accessibility, focus management, and responsive behavior.
react-autosuggest: Flexible Foundationreact-autosuggest doesn’t render any DOM for you. Instead, it manages the suggestion state and passes props to your custom components via a render-prop pattern. This gives you total control over markup and behavior.
// react-autosuggest
import Autosuggest from 'react-autosuggest';
const inputProps = {
placeholder: 'Type a programming language',
value,
onChange: (_, { newValue }) => setValue(newValue)
};
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={({ value }) => {
setSuggestions(getSuggestions(value));
}}
onSuggestionsClearRequested={() => setSuggestions([])}
getSuggestionValue={(suggestion) => suggestion.name}
renderSuggestion={(suggestion) => <div>{suggestion.name}</div>}
inputProps={inputProps}
/>
You must implement ARIA attributes, keyboard navigation, and screen reader support manually — which is powerful but error-prone.
react-select: Full-Featured Componentreact-select ships with a complete, accessible UI. It handles ARIA roles, keyboard navigation (arrow keys, Enter, Escape), focus trapping, and screen reader announcements out of the box.
// react-select
import Select from 'react-select';
const options = [
{ value: 'javascript', label: 'JavaScript' },
{ value: 'python', label: 'Python' }
];
<Select
options={options}
value={selectedOption}
onChange={setSelectedOption}
placeholder="Choose a language"
/>
It also supports advanced patterns like async loading, creatable options, and multi-select without extra wiring.
react-autocomplete: You filter items yourself in the parent component and pass the filtered list to items.react-autosuggest: You control filtering in onSuggestionsFetchRequested. Great for debouncing or custom logic.react-select: Filters options automatically by label (or a custom filterOption function).// react-select custom filter
const customFilter = (option, inputValue) =>
option.data.tags.some(tag => tag.includes(inputValue));
<Select filterOption={customFilter} ... />
react-autocomplete: No built-in support. You’d manage loading states externally.react-autosuggest: You handle async calls in onSuggestionsFetchRequested.react-select: Use the AsyncSelect or AsyncCreatableSelect components.// react-select async
import AsyncSelect from 'react-select/async';
const loadOptions = (inputValue) =>
fetch(`/api/search?q=${inputValue}`).then(res => res.json());
<AsyncSelect loadOptions={loadOptions} ... />
react-autocomplete: Style via inline styles or CSS classes. No theming system.react-autosuggest: Entirely up to you — you render the DOM.react-select: Offers a powerful styles prop (for inline JS styles) and a theme prop (for structural theming).// react-select custom styling
const customStyles = {
control: (base) => ({ ...base, backgroundColor: 'lightblue' }),
option: (base, state) => ({
...base,
backgroundColor: state.isFocused ? 'pink' : 'white'
})
};
<Select styles={customStyles} ... />
react-autocomplete: Not ARIA-compliant. Missing roles, live regions, and proper focus management.react-autosuggest: Requires manual implementation of ARIA attributes (aria-activedescendant, aria-expanded, etc.).react-select: Fully compliant with WAI-ARIA practices for comboboxes. Tested with major screen readers.| Feature | react-autocomplete | react-autosuggest | react-select |
|---|---|---|---|
| Multi-select | ❌ | ❌ (manual) | ✅ |
| Creatable options | ❌ | ❌ (manual) | ✅ |
| Grouped options | ❌ | ❌ (manual) | ✅ |
| Async loading | ❌ | ✅ (manual) | ✅ |
| Built-in accessibility | ❌ | ❌ | ✅ |
| TypeScript support | ❌ | ✅ | ✅ |
react-autocomplete — it’s deprecated and unsafe for modern apps.react-autosuggest only if you have a design system that demands pixel-perfect control over every aspect of the UI and you have resources to implement and test accessibility thoroughly.react-select for 90% of cases — it’s production-ready, accessible, and saves weeks of development time. Its theming and composition APIs are flexible enough for most custom needs without sacrificing reliability.In short: unless you’re building a design system from scratch, react-select is the pragmatic choice for professional teams shipping robust user interfaces.
Choose react-select for most production applications where you need a robust, accessible, and feature-rich select or autocomplete component out of the box. It includes built-in support for multi-select, async loading, creatable options, grouping, and extensive theming. Its comprehensive API reduces implementation time while maintaining good accessibility compliance, making it suitable for enterprise-grade forms and admin interfaces.
Choose react-autocomplete only if you're maintaining a legacy codebase that already uses it. The package is deprecated and no longer actively maintained, so it should not be used in new projects. It provides basic autocomplete functionality but lacks modern accessibility support, customization APIs, and TypeScript definitions out of the box.
Choose react-autosuggest when you need a lightweight, unopinionated foundation for building highly custom autocomplete experiences. It gives you full control over rendering, styling, and interaction logic, but requires you to implement accessibility, keyboard navigation, and UI state management yourself. Ideal for teams with strong design systems or unique UX requirements that can't be met by more opinionated libraries.
The Select control for React. Initially built for use in KeystoneJS.
See react-select.com for live demos and comprehensive docs.
React Select is funded by Thinkmill and Atlassian. It represents a whole new approach to developing powerful React.js components that just work out of the box, while being extremely customisable.
For the story behind this component, watch Jed's talk at React Conf 2019 - building React Select
Features include:
The easiest way to use react-select is to install it from npm and build it into your app with Webpack.
yarn add react-select
Then use it in your app:
import React from 'react';
import Select from 'react-select';
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
];
class App extends React.Component {
state = {
selectedOption: null,
};
handleChange = (selectedOption) => {
this.setState({ selectedOption }, () =>
console.log(`Option selected:`, this.state.selectedOption)
);
};
render() {
const { selectedOption } = this.state;
return (
<Select
value={selectedOption}
onChange={this.handleChange}
options={options}
/>
);
}
}
import React, { useState } from 'react';
import Select from 'react-select';
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
];
export default function App() {
const [selectedOption, setSelectedOption] = useState(null);
return (
<div className="App">
<Select
defaultValue={selectedOption}
onChange={setSelectedOption}
options={options}
/>
</div>
);
}
Common props you may want to specify include:
autoFocus - focus the control when it mountsclassName - apply a className to the controlclassNamePrefix - apply classNames to inner elements with the given prefixisDisabled - disable the controlisMulti - allow the user to select multiple valuesisSearchable - allow the user to search for matching optionsname - generate an HTML input with this name, containing the current valueonChange - subscribe to change eventsoptions - specify the options the user can select fromplaceholder - change the text displayed when no option is selectednoOptionsMessage - ({ inputValue: string }) => string | null - Text to display when there are no optionsvalue - control the current valueSee the props documentation for complete documentation on the props react-select supports.
You can control the following props by providing values for them. If you don't, react-select will manage them for you.
value / onChange - specify the current value of the controlmenuIsOpen / onMenuOpen / onMenuClose - control whether the menu is openinputValue / onInputChange - control the value of the search input (changing this will update the available options)If you don't provide these props, you can set the initial value of the state they control:
defaultValue - set the initial value of the controldefaultMenuIsOpen - set the initial open value of the menudefaultInputValue - set the initial value of the search inputReact-select exposes two public methods:
focus() - focus the control programmaticallyblur() - blur the control programmaticallyCheck the docs for more information on:
The v5 release represents a rewrite from JavaScript to TypeScript. The types for v4 and earlier releases are available at @types. See the TypeScript guide for how to use the types starting with v5.
Thank you to everyone who has contributed to this project. It's been a wild ride.
If you like React Select, you should follow me on twitter!
Shout out to Joss Mackison, Charles Lee, Ben Conolly, Tom Walker, Nathan Bierema, Eric Bonow, Emma Hamilton, Dave Brotherstone, Brian Vaughn, and the Atlassian Design System team who along with many other contributors have made this possible ❤️
MIT Licensed. Copyright (c) Jed Watson 2022.