Editor’s note: This article was last updated on 15 December 2022 to reflect changes made in React Select v5.
When working on a web project three or four years ago, select elements used to be one of the easiest things to build. However, nowadays, a lot more goes into building select elements, especially when UI and UX is a high priority.
For example, one must consider features like on-focus, fetching data from a remote source, styling select elements, and more. When working on a React project, you may have wished that a reusable component existed somewhere in the multiverse.
Luckily for us, Jed Watson began an open source project funded by his company, Thinkmill, and Atlassian called React Select. In this article, we’ll explore some of the awesome features included in React Select v5, then learn how to get started with React Select with a simple example. You can also check out our video tutorial on React Select. Let’s get started!
- Prerequisites
- Installing React Select
- Basic usage of React Select
- Add Bootstrap
- Using
onChange
andautofocus
props - Adding custom styles to React Select components
- Custom components
- Multi-select
- Using React Select with SSR
- Async and Fixed Options
Prerequisites
To follow along with this tutorial, you’ll need the following:
- Yarn or npm installed on your machine
- Create React App CLI tool installed
- A basic understanding of HTML, JavaScript ES6, and CSS
- A basic understanding of the React framework
- A basic understanding of the command line terminal
Installing React Select
With these requirements out of the way, we’ll first add the React Select package to our existing React application. For the sake of this tutorial, we’ll use the Create React App CLI tool.
If you don’t already have an existing project, you can create one with the following code:
npx create-react-app my-app # OR yarn create react-app my-app
With that done, we can install the React Select package with the following command:
npm install react-select # OR yarn add react-select
Now, we’ll take a look at how we can import and use the React Select package in a React application.
Basic usage of React Select
To get started with React Select, we just need to import its Select
component and add an array of objects that contain the options and their corresponding labels:
// App.js import Select from "react-select"; const App = () => { const options = [ { value: "blues", label: "Blues" }, { value: "rock", label: "Rock" }, { value: "jazz", label: "Jazz" }, { value: "orchestra", label: "Orchestra" }, ]; return ( <div> <Select options={options} /> </div> ); }; export default App;
In the code snippet above, we have our select options as music genres, which are passed into the select
component as props. When we run this application, we should see a select
element that spans the screen from one end to the other:
In the following sections, we’ll see how we can style the select
component to extend its functionalities and make it more visually appealing. But first, we’ll add Bootstrap to our application to help with structuring and prevent our select
component from taking up the entire webpage width.
Add Bootstrap
We can install Bootstrap in our project as follows:
npm install bootstrap # OR yarn add boostrap
With Bootstrap installed, we’ll utilize its utility classes to restructure our application:
//App.js import Select from "react-select"; // Import Bootstarp CSS import "bootstrap/dist/css/bootstrap.css"; const App = () => { const options = [ { value: "blues", label: "Blues" }, { value: "rock", label: "Rock" }, { value: "jazz", label: "Jazz" }, { value: "orchestra", label: "Orchestra" }, ]; return ( <div className="container"> <div className="mt-5 m-auto w-50"> <Select options={options} /> </div> </div> ); }; export default App;
The code above will give us a select
element that looks like the following image:
Using onChange
and autofocus
props
Getting the value from the React Select component is comparable to how we’ll do it with a traditional HTML input; we can do so by leveraging its onChange
event, along with the React useState
Hook as follows:
import { useState } from "react"; import Select from "react-select"; import "bootstrap/dist/css/bootstrap.css"; const App = () => { const options = [ { value: "blues", label: "Blues" }, { value: "rock", label: "Rock" }, { value: "jazz", label: "Jazz" }, { value: "orchestra", label: "Orchestra" }, ]; const [selected, setSelected] = useState(null); const handleChange = (selectedOption) => { setSelected(selectedOption); console.log(`Option selected:`, selectedOption); }; return ( <div className="container"> <div className="mt-5 m-auto w-50"> <Select options={options} onChange={handleChange} autoFocus={true} /> <div className="mt-4"> {selected && <>You've selected {selected.value}</>} </div> </div> </div> ); }; export default App;
In the code above, we added a handleChange
function to the onChange
event, so that whenever a user changes their option in the select
component, our state is updated to an object containing the selected option value and label.
Therefore, if we choose rock
as an option, our console would display something like the following:
Option selected: {value:"rock", label: "Rock"}
This is useful when we want to manipulate the data obtained from our React Select component. We also have the autoFocus
prop, which accepts a boolean
value and is used to add autoFocus
to the select
component on page load. To learn more about the props available for use, you can check out the props documentation for React Select.
Adding custom styles to React Select components
React Select is fully customizable, allowing us to style each unit, like control
, options
, placeholder
, and many more of our select
components. We can accomplish this by passing an additional styles
prop containing the new preferred styling for each unit:
During this process, we can also access and choose to add default styling for each unit. We can also add styling on demand, meaning we specify what styling an option should have if it is selected or focused on, etc.
To try all this out, paste the following code into the App.js
file:
import Select from "react-select"; import "bootstrap/dist/css/bootstrap.css"; const App = () => { const options = [ { value: "blues", label: "Blues" }, { value: "rock", label: "Rock" }, { value: "jazz", label: "Jazz" }, { value: "orchestra", label: "Orchestra" }, ]; const customStyles = { option: (defaultStyles, state) => ({ ...defaultStyles, color: state.isSelected ? "#212529" : "#fff", backgroundColor: state.isSelected ? "#a0a0a0" : "#212529", }), control: (defaultStyles) => ({ ...defaultStyles, backgroundColor: "#212529", padding: "10px", border: "none", boxShadow: "none", }), singleValue: (defaultStyles) => ({ ...defaultStyles, color: "#fff" }), }; return ( <div className="container"> <div className="mt-5 m-auto w-50 text-light"> <Select options={options} styles={customStyles} /> </div> </div> ); }; export default App;
In the code above, we modified the select
component to add custom styling to the select control
, its options via option
, and the currently selected option via singleValue
. We made the changes to give our select
component a dark mode appearance. When you run your application, you should have an output similar to the one below:
Custom components
Under styles and states, we discussed two custom components, option
and control
, which we used to extend the select
styling. In this section, we’ll take a look at another custom component called Custom SingleValue
.
This custom component does what our regular select
component does, but we’ll add a little finesse. In our App.js
file, we’ll import the React
and Select
packages from React and React Select with the code below:
import Select, { components } from 'react-select'; . . .
When we’re done, we’ll have a finished dropdown that looks something like the following:
In the code block below, we define our custom SingleValue
component as a method that extends the base component in the React Select package. In our App
class, we have a couple of props and functions that contribute to the functionality shown in the image above:
import { useState } from "react"; import "bootstrap/dist/css/bootstrap.css"; import Select, { components } from "react-select"; const Control = ({ children, ...props }) => ( <components.Control {...props}> Click to Select → {children} </components.Control> ); const App = () => { const options = [ { value: "blue", label: "Blue" }, { value: "green", label: "Green" }, { value: "orange", label: "Orange" }, { value: "purple", label: "Purple" }, ]; const customStyles = { singleValue: (base) => ({ ...base, padding: "5px 10px", borderRadius: 5, background: selected, color: "white", display: "flex", width: "fit-content", }), }; const [selected, setSelected] = useState(""); var handleChange = (selected) => { setSelected(selected.value); }; return ( <div className="container"> <div className="mt-5 m-auto w-50"> <Select onChange={handleChange} styles={customStyles} components={{ Control }} options={options} /> </div> </div> ); }; export default App;
Multi-select
We can configure React Select to allow multiple options to be selected in a single select
component. This is accomplished by including the isMulti
property in our select
component:
import { useState } from "react"; import "bootstrap/dist/css/bootstrap.css"; import Select from "react-select"; function App() { const options = [ { value: "blue", label: "Blue" }, { value: "green", label: "Green" }, { value: "orange", label: "Orange" }, { value: "purple", label: "Purple" }, ]; const [selectedOption, setSelectedOption] = useState(""); var handleChange = (selectedOption) => { console.log(selectedOption); setSelectedOption(selectedOption.value); }; return ( <div className="container"> <div className="mt-5 m-auto w-50"> <Select isMulti onChange={handleChange} options={options} /> </div> </div> ); } export default App;
When we run our code, we’ll have the following output:
Using React Select with SSR
When you try to use the React Select component with server-side rendering (SSR) frameworks like Next.js, you might get a reference error like the one below:
ReferenceError: window is not defined
The browser’s window object is unavailable with SSR until a component is fully mounted. However, React Select is dependent on the browser window
object to function. Because we’re importing the React Select library before the component is mounted, we’ll get the reference is not defined
error.
We can fix this error in Next.js by using the dynamic import function with the ssr
option disabled, as shown below:
import dynamic from 'next/dynamic' const Select = dynamic(() => import("react-select"), { ssr: false, })
You can also use popular packages like the react-no-ssr package for implementation in other frameworks.
Async and Fixed Options
There are a few other concepts that are important to know in regard to working with the React Select component, one of which is the Async component. This component comes in handy when requesting your select
values or options from an API or a database query. The Async component includes provision for helpful props like:
cacheOptions
: Caching fetched optionsdefaultOptions
: Set default options before the remote options are loaded
Another component that may come in handy is the Fixed Options component, which makes it possible to have fixed options.
Conclusion
In this article, we’ve explored some common use cases for the React Select component. We also learned how to get started with React Select and extend some of its predefined components to suit our needs.
There are a plethora of functionalities built into the React Select package, some of which will fit your needs, and some of which you’ll have to customize to fit your use case.
To get your hands dirty, I recommend checking out the official documentation. Feel free to leave a comment if you have questions or get stuck. Happy coding!
Get setup with LogRocket's modern React error tracking in minutes:
- Visit https://logrocket.com/signup/ to get an app ID.
- Install LogRocket via NPM or script tag.
LogRocket.init()
must be called client-side, not server-side. - (Optional) Install plugins for deeper integrations with your stack:
- Redux middleware
- ngrx middleware
- Vuex plugin
$ npm i --save logrocket
// Code:
import LogRocket from 'logrocket';
LogRocket.init('app/id');
Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
How do you get the value out of react-select? I’ve set up a working react-select async component that pulls data from an external api and populates the component with the suggestions. That is working great. However, getting the value from the component is proving rather tricky…
I have a ‘submit’ button that (when clicked on) pulls the stored data to be dynamically added to a table on another portion of my site. However, every time I click on the submit button, react-select automatically clears the stored input (in react state) and it comes back as an empty string. Soo frustrating!
Wish you had covered this is your write up!
Hi, maybe you have an example of how to use ‘react-select’ with server-side rendering? I’m trying to upgrade react (and other components) to the latest version, and everything works well except this ‘react-select’ component: when I use it with server-side rendering there is an error:
‘ReferenceError: window is not defined’
Seems like I have some wrong configuration in webpack or something wrong in a component where I use ‘react-select’; I did some investigation and I found out that in my generated ‘server.js’ it uses code from ‘react-select-*.browser.*.js’, but probably it should use code ‘from react-select-*.prod.js’?
Thanks in advance
If i create a custom component .it always rerenders.how can i stop it?
If your useEffect is updating your state, and your state var is in the useEffect [] array, the state update will trigger a rerender, and the rerender will update your state which will cause a rerender which … repeat endlessly. Take your state var out of your useEffect [] array. That should help.