How To Create Searchable, Async Dropdowns with React-Select
Table of Contents
Introduction #
HTML provides a <select>
element that allows end-users to choose from a dropdown menu of <option>
s. However, there may be situations where a select menu can benefit from additional user experience niceties, like allowing a user to filter available choices.
React Select is a highly configurable select menu library for React that features dynamic search and filter. It also supports async option loading, accessibility, and fast render times.
In this tutorial, you will add React Select to a project. You will also explore some of the additional features available: multi-select, user-creatable options, and async option loading.
Prerequisites #
To complete this tutorial, you’ll need:
A local development environment for Node.js. Follow How to Install Node.js and Create a Local Development Environment to accomplish this.
This tutorial was verified with Node v14.7.0, npm
v6.14.7, react
v16.13.1, and react-select
v3.1.0.
Step 1 — Setting Up the Project #
Start with using create-react-app
to generate a React App and then install dependencies:
npx create-react-app react-select-example
Change into the new project directory:
cd react-select-example
Now, you can run the React application:
npm start
Fix any errors or issues with your project, then visit localhost:3000
in a web browser.
Once you have a working React application, you can start adding React Select.
Step 2 — Adding React Select #
Your project will require installing the react-select
library:
npm install react-select@3.1.0
Note: Presently, there is an issue with the latest version of the library (3.1.0), where it generates warnings for legacy and deprecated API when using StrictMode
. These are known issues, and a few pending pull requests will address some of them.
Here is an example of modifying App.js
to display a dropdown menu of aquatic animals:
nano src/App.js
Add an array for aquaticCreatures
and use the Select
component provided by React Select:
src/App.js
import React from 'react';
import Select from 'react-select';
const aquaticCreatures = [
{ label: 'Shark', value: 'Shark' },
{ label: 'Dolphin', value: 'Dolphin' },
{ label: 'Whale', value: 'Whale' },
{ label: 'Octopus', value: 'Octopus' },
{ label: 'Crab', value: 'Crab' },
{ label: 'Lobster', value: 'Lobster' },
];
function App() {
return (
<div className="App">
<Select
options={aquaticCreatures}
/>
</div>
);
}
export default App;
You will notice three things:
You must import the Select
component from react-select
.
Each object in the options array aquaticCreatures
must have at least two values: label
, a string, and value
, which may be any type.
The only required prop is the options
array.
Note: If you are populating your React Select component with an array of strings, rather than manually repeating label
and value
, you can use JavaScript’s map array method to prepare the options
array:
someArrayOfStrings.map(opt => ({ label: opt, value: opt }));
To capture when the user selects an option, add the onChange
prop:
src/App.js
<Select
options={aquaticCreatures}
onChange={opt => console.log(opt.label, opt.value)}
/>
The value passed to the onChange
function is the same object that makes up the option itself, so it will contain the label
and value
variables.
Run your project:
npm start
Then, visit localhost:3000
in your web browser.
You will be presented with a React Select menu with aquaticCreatures
:
If you interact with this menu, you will trigger an onChange
event and log messages to the console. By opening your browser’s developer console, you should observe the label
and value
of your choices:
'Shark' 'Shark'
Now that you have a working React Select menu, you can explore some of the other features this library provides.
Step 3 — Adding Advanced Options #
In addition to search and selection, React Select offers other features like multi-select, user-creatable options, and async option loading.
Multi-Select #
HTML <select>
supports multiple
to allow selecting multiple <option>
s.
Similarly, in React Select, you can enable multi-select by adding the isMulti
prop to your element:
src/App.js
<Select
options={aquaticCreatures}
isMulti
/>
For exploration purposes, the onChange
prop will also need to be modified to support multi-select because opt
is no longer a single object. With multi-select, it becomes a nested object. opt.label
and opt.value
would have otherwise returned undefined
.
src/App.js
<Select
options={aquaticCreatures}
isMulti
onChange={opt => console.log(opt)}
/>
Run your project:
npm start
Then, visit localhost:3000
in your web browser.
Select an option from the aquaticCreatures
, and then select another. All of your multiple selections should be indicated by the component:
That concludes the multi-select feature.
User-Creatable Options #
You can provide user-creatable options to allow users to add custom values to the select menu in situations where the choice they want is not present in the menu.
First, you need to import the Creatable
component from react-select/creatable
:
src/App.js
import Creatable from 'react-select/creatable';
Then, replace the Select
component with Creatable
:
src/App.js
<Creatable
options={aquaticCreatures}
/>
For exploration purposes, the onChange
prop will also need to be modified to display the meta
value:
src/App.js
<Creatable
options={aquaticCreatures}
onChange={(opt, meta) => console.log(opt, meta)}
/>
Run the project:
npm start
When you type an option that does not currently exist—like Cuttlefish
—you will be presented with a 'Create'
option:
After creating the new menu item, you should observe the following in your browser’s developer console output:
{ label: 'Cuttlefish', value: 'Cuttlefish', __isNew__: true }
{ action: 'create-option' }
Notice that you have two ways of detecting that the event is a new option: the __isNew__
variable of your selected option and the action
value of the meta
argument in the event handler.
Also, notice how the label
and value
will be identical strings. Users are not provided with an option to provide a label
with a different value
, which may affect how you approach your solution for consistency in your data store.
That concludes the user-creatable options feature.
Async Option Loading #
You can use async option loading to allow users to experience faster initial loading times in your application. This will only populate the component when the user interacts with it.
Much like the Creatable
component, you will need to import AsyncSelect
from react-select/async
:
import AsyncSelect from 'react-select/async'
Then, replace the Select
component with Async
:
src/App.js
<AsyncSelect
loadOptions={loadOptions}
/>
To load the options, pass the loadOptions
prop a function, similar to the following:
const loadOptions = (inputValue, callback) => {
// perform a request
const requestResults = ...
callback(requestResults)
}
React Select also supports the defaultOptions
prop, which calls the loadOptions
function on initialization to populate the dropdown, and the cacheOptions
prop, which caches the options while its value is truthy.
That concludes the async option loading feature.
Conclusion #
In this tutorial, you added React Select to a project. The customization and feature set of React Select has the potential to provide your users with a greater user experience than a standard select menu.
Additional information about the props and advanced features can be found in the React Select documentation.
If you’d like to learn more about React, take a look at our How To Code in React.js series, or check out our React topic page for exercises and programming projects.