React Select Example | React Dropdown Menu - Fully Customizable
In this post you will learn how to implement single select and multi select and customize it inside React.
And actually what I want to show you is a library and not a custom implementation. I'm not a fan of using libraries but there are some usecases where it is much easier to use a library than to implement it on your own.
The library that I want to show you is called React-select. This is the most popular library to work with single and multi select inside React. It has an amazing API and is really customizable.
This is why here I want to show you 5 different ways how you can use this library for your everyday needs. To install this library you can write
yarn add react-select
Single select
Now let's look on the first way of usage. This is just a usage of single select with predefined data which are static.
const App = () => {
const options = [
{ value: "jack", label: "Jack" },
{ value: "john", label: "John" },
{ value: "mike", label: "Mike" },
];
return (
<h1>Hello monsterlessons</h1>
);
};
Here we just have options with value
and label
. This is the format in which React-select accepts data.
Now let's import a single select.
import Select from "react-select";
...
return <Select options={options} />
We just used Select
and provided our options inside. This is the bare minimum to use this library.
As you can see inside browser we are getting a select. It is already customized, styled, we can open it we see our users inside.
But obviously we want to react on user selection in some way and for this we have onChange
.
const handleChange = selectedOption => {
console.log('handleChange', selectedOption)
}
return <Select options={options} onChange={handleChange} />
Now every single time when we select a user we get a callback with our user object.
Multiselect
The next usage that we want to React-select is obviously multiselect. It is extremely easy to add it. We don't need to change anything at all but just provide isMulti
.
return <Select options={options} onChange={handleChange} isMulti />
It will directly change the whole single select to multi select.
As you can see it is already changed to milti select. When we select an item we see several selected elements and in our callback we get an array instead of the single object.
Async data
Here is a usecase that you for sure need. It is working with async data. Typically we don't just have static data for a select but we get this data from API and it is fully dynamic.
import AsyncSelect from 'react-select/async'
...
const loadOptions = (searchValue, callback) => {
setTimeout(() => {
const filteredOptions = options.filter(option => {
return option.label.toLowerCase().includes(searchValue.toLowerCase())
})
console.log('loadOptions', searchValue, filteredOptions)
callback(filteredOptions)
}, 2000)
...
return <AsyncSelect loadOptions={loadOptions} onChange={handleChange} isMulti />
}
Here we used AsyncSelect
instead and passed loadOptions
function to it. Load options function it designed to get asynchronous data from API by some searchValue
. This is why we wrap the code in timeout to simulate long API call and filter our options by searchValue
.
To tell select that we are ready with our asynchronous code we must call callback
function and provide array of options inside.
As you can see in browser nothing happens by default. Our select is empty. But when we type something in it our loadOptions
will happen and after some time we will get data just like from the API..
But typically you want to load all data on initialize. We can do that by adding one more parameter. And this parameter is called defaultOptions
.
return <AsyncSelect loadOptions={loadOptions} onChange={handleChange} isMulti defaultOptions />
Now on initialize after 2 seconds we get all data.
You must keep in mind that if you have a lot of data on backend loading it all without filtering is not the best idea.
Styling select
The next important case that you need in your project is customizing and styling of the select. It is totally possible to do it inside select.
const colorStyles = {
control: (styles) => ({ ...styles, backgroundColor: "white" })
}
return <Select options={options} onChange={handleChange} styles={colorStyles} />
We can customize different parts of select by providing styles. Here we changed just control property. Inside we pass a function where we get access to all default styles of this elements and can override them.
Now let's do the same with all elements.
const colorStyles = {
control: (styles) => ({ ...styles, backgroundColor: "white" }),
option: (styles, { data, isDisabled, isFocused, isSelected }) => {
return { ...styles, color: data.color };
},
multiValue: (styles, { data }) => {
return {
...styles,
backgroundColor: data.color,
color: "#fff",
};
},
multiValueLabel: (styles, { data }) => {
return {
...styles,
color: "#fff",
};
},
multiValueRemove: (styles, { data }) => {
return {
...styles,
color: "#fff",
cursor: "pointer",
":hover": {
color: "#fff",
},
};
},
};
We do exactly the same with different properties. As you can see we also have access to data
, isDisabled
, isFocused
, isSelected
so we can apply styles for different usecases.
Creatable React select
The last case that I want to show you is creatable select. Inside the select we can directly create new options.
import CreatableSelect from "react-select/creatable";
return (
<CreatableSelect
options={options}
onChange={handleChange}
isMulti
styles={colorStyles}
/>
);
The whole code stays the same but we use CreatableSelect
now. When we type some text we can click on it and this option will be passed in handleChange
function.
Bonus
But it is not all. I want to show you 2 callbacks that you can use to react on some changes in select.
const handleChange = (selectedOption, actionMeta) => {
console.log("handleChange", selectedOption, actionMeta);
};
const handleInputChange = (inputValue, actionMeta) => {
console.log("handleInputChange", inputValue, actionMeta);
};
return (
<CreatableSelect
options={options}
onChange={handleChange}
onInputChange={handleInputChange}
isMulti
styles={colorStyles}
/>
);
Here we defined onInputChange
. Also we added actionMeta
to both callbacks. Now if you try to add elements you get different logs about what happens inside a select like focus, blur, select element on which you can react.
Want to conquer your next JavaScript interview? Download my FREE PDF - Pass Your JS Interview with Confidence and start preparing for success today!
📚 Source code of what we've done