I’ve found that building a custom dropdown from scratch is often a recipe for a headache.
Whether it’s handling keyboard navigation or managing complex multi-select states, the built-in HTML select element often falls short of modern UI requirements.
Whenever I need a robust, flexible, and accessible select menu, I almost always reach for the react-select library.
It is a powerful tool that transforms a simple dropdown into a feature-rich component with very little effort.
In this tutorial, I will show you exactly how to implement and customize the React Select component using examples you’ll actually use in production.
Why Use React Select?
Standard HTML select elements are difficult to style and lack advanced features like searching or tagging.
React Select provides these features out of the box, ensuring a consistent look and feel across different browsers.
I prefer it because it handles the heavy lifting of accessibility (Aria attributes) and state management for me.
Install React Select
Before we jump into the code, you need to add the package to your React project.
You can do this by running the following command in your terminal:
npm install react-selectOnce installed, you are ready to start building your first enhanced dropdown.
Method 1: Create a Basic Searchable Select
One of the most common tasks I handle is creating a picker for geographical data, such as selecting a US State.
In this example, we will create a simple searchable dropdown where a user can pick a state from a list.
import React, { useState } from 'react';
import Select from 'react-select';
const usStates = [
{ value: 'AL', label: 'Alabama' },
{ value: 'AK', label: 'Alaska' },
{ value: 'AZ', label: 'Arizona' },
{ value: 'CA', label: 'California' },
{ value: 'NY', label: 'New York' },
{ value: 'TX', label: 'Texas' },
];
const BasicStateSelect = () => {
const [selectedState, setSelectedState] = useState(null);
const handleChange = (selectedOption) => {
setSelectedState(selectedOption);
console.log(`Option selected:`, selectedOption);
};
return (
<div style={{ padding: '20px', maxWidth: '400px' }}>
<h3>Select a US State</h3>
<Select
value={selectedState}
onChange={handleChange}
options={usStates}
isSearchable={true}
placeholder="Search for a state..."
/>
{selectedState && (
<div style={{ marginTop: '20px' }}>
<strong>You selected:</strong> {selectedState.label}
</div>
)}
</div>
);
};
export default BasicStateSelect;You can see the output in the screenshot below.

In this setup, I defined an array of objects where each object has a value and a label. React Select specifically looks for these keys to render the options and track the state.
Method 2: Implement a Multi-Select Component
In many CRM or HR platforms I’ve worked on, users often need to select multiple categories or tags.
Using the isMulti prop, React Select turns the dropdown into a tagging system automatically.
Let’s look at an example where a user selects multiple US Time Zones for a meeting.
import React, { useState } from 'react';
import Select from 'react-select';
const timeZones = [
{ value: 'EST', label: 'Eastern Standard Time' },
{ value: 'CST', label: 'Central Standard Time' },
{ value: 'MST', label: 'Mountain Standard Time' },
{ value: 'PST', label: 'Pacific Standard Time' },
{ value: 'HST', label: 'Hawaii-Aleutian Standard Time' },
];
const MultiTimeZoneSelect = () => {
const [selectedZones, setSelectedZones] = useState([]);
const handleChange = (options) => {
setSelectedZones(options);
};
return (
<div style={{ padding: '20px', maxWidth: '500px' }}>
<h3>Select Applicable Time Zones</h3>
<Select
isMulti
name="timezones"
options={timeZones}
className="basic-multi-select"
classNamePrefix="select"
onChange={handleChange}
placeholder="Choose zones..."
/>
<div style={{ marginTop: '15px' }}>
{selectedZones.length > 0 && (
<p>You have selected {selectedZones.length} zones.</p>
)}
</div>
</div>
);
};
export default MultiTimeZoneSelect;You can see the output in the screenshot below.

When isMulti is active, the onChange function receives an array of objects instead of a single object.
I find this incredibly useful for filtering dashboards where multiple criteria are required.
Method 3: Fetch Options Asynchronously (Async Select)
Sometimes, the list of options is too large to load all at once, like a list of every city in the US. In these cases, I use AsyncSelect to fetch data from an API only when the user starts typing.
This keeps the initial bundle size small and the application snappy.
import React from 'react';
import AsyncSelect from 'react-select/async';
const CityAsyncSelect = () => {
// Simulated API call to fetch US Cities
const loadOptions = (inputValue, callback) => {
setTimeout(() => {
const cities = [
{ value: 'nyc', label: 'New York City' },
{ value: 'la', label: 'Los Angeles' },
{ value: 'chi', label: 'Chicago' },
{ value: 'hou', label: 'Houston' },
{ value: 'phx', label: 'Phoenix' },
];
const filtered = cities.filter((i) =>
i.label.toLowerCase().includes(inputValue.toLowerCase())
);
callback(filtered);
}, 1000);
};
return (
<div style={{ padding: '20px', maxWidth: '400px' }}>
<h3>Search US Cities (Async)</h3>
<AsyncSelect
cacheOptions
loadOptions={loadOptions}
defaultOptions
placeholder="Type to search cities..."
onChange={(opt) => console.log('City Selected:', opt)}
/>
</div>
);
};
export default CityAsyncSelect;You can see the output in the screenshot below.

The cacheOptions prop is a lifesaver here as it prevents redundant API calls for the same search term.
I always recommend using defaultOptions so the user isn’t staring at an empty box when they first click it.
Method 4: Custom Styling with the Styles API
The default look of React Select is clean, but it rarely matches a brand’s specific color palette.
I often use the styles prop to override specific parts of the component, like the control or the options.
Here is how I would style a dropdown to match a “Dark Mode” US Financial Dashboard.
import React from 'react';
import Select from 'react-select';
const stockExchanges = [
{ value: 'nyse', label: 'New York Stock Exchange' },
{ value: 'nasdaq', label: 'NASDAQ' },
{ value: 'amex', label: 'American Stock Exchange' },
];
const customStyles = {
control: (provided, state) => ({
...provided,
backgroundColor: '#2c3e50',
borderColor: state.isFocused ? '#3498db' : '#7f8c8d',
color: 'white',
}),
menu: (provided) => ({
...provided,
backgroundColor: '#2c3e50',
}),
option: (provided, state) => ({
...provided,
backgroundColor: state.isFocused ? '#3498db' : '#2c3e50',
color: 'white',
cursor: 'pointer',
}),
singleValue: (provided) => ({
...provided,
color: 'white',
}),
};
const StyledSelect = () => (
<div style={{ padding: '20px', maxWidth: '400px' }}>
<h3>Custom Styled Select</h3>
<Select
options={stockExchanges}
styles={customStyles}
placeholder="Select Exchange..."
/>
</div>
);
export default StyledSelect;This approach is much cleaner than using global CSS because it keeps the styles scoped to the component.
Best Practices for Using React Select
Through the years, I’ve learned a few tricks to make React Select work even better in production.
First, always provide a placeholder that describes the expected action, like “Select a Department.”
Second, if you are using it within a form, make sure to use a controller if you are using libraries like React Hook Form.
Third, if your list of options is static, define the array outside of the component to prevent unnecessary re-renders.
Finally, keep an eye on performance if you have thousands of options; you might need react-window to virtualize the list.
Using React Select can significantly improve the user experience of your forms by providing a familiar and powerful interface.
You may also like to read:
- How to Build a Custom Table Component in React MUI
- How to Get Component Height in React
- React Component Props with TypeScript
- Component-Based Architecture in React

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.