Open-source project
JedWatson/react-select avatar
JedWatson/react-select

react-select: a select control for React that you can restyle and control

The Select Component for React.js

28,026 stars4,097 forksTypeScriptMIT

At a glance

What is it?
react-select is a React component for dropdowns and multi-selects, with controllable state props and a styling API built on emotion. It suits teams that need option groups, async loading or custom option rendering, and it costs you a dependency and a styling model to learn.
Who is it for?
Adopt react-select when you need a React select with option groups, multi-select, portal support or a styling API you can extend, and when you are willing to learn its props and emotion-based styles. Do not adopt it if a native select element or a small headless primitive already covers your case, because you would be adding a component library and a styling dependency for behaviour you do not use.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 76 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What react-select replaces, and who ends up using it

A native select element is small, accessible and free, but it cannot render arbitrary option content, group options with custom headers, or load choices from a server as the user types. Building those behaviours by hand means writing keyboard handling, focus management, menu positioning and a filtering loop, then maintaining all of it. react-select exists to absorb that work. The README describes it as "The Select control for React", initially built for KeystoneJS, and says it helps you develop select components that work out of the box without stopping you from customising the parts that matter.

The audience is React application teams that have outgrown the native control but do not want to assemble a dropdown from primitives. The feature list points at specific needs: option groups, portal support, animation, an extensible styling API built on emotion, and a component injection API for control over UI behaviour. If your form only ever picks one value from five static strings, none of this earns its place. If your form picks users from a paginated API, renders avatars next to names, and needs the menu to escape an overflow-hidden container, the component is aimed at you.

How the component manages state, options and rendering

The mechanism is a controlled or uncontrolled component with a small set of stateful props. The README lists three pairs: value with onChange, menuIsOpen with onMenuOpen and onMenuClose, and inputValue with onInputChange. Supply a pair and you own that state; omit it and react-select manages it internally. For each pair there is a default prop that sets only the initial value: defaultValue, defaultMenuIsOpen, defaultInputValue. That split is the whole architecture in miniature, and it is the part worth understanding before you write code, because mixing controlled and uncontrolled usage of the same field is where bugs come from.

Options are plain objects. The README example uses value and label keys, and notes that the approach to data is flexible with customisable functions, so the mapping from your data shape to the rendered option is yours to define. Filtering, when enabled through isSearchable, runs against the input value, and noOptionsMessage is a function of the shape ({ inputValue: string }) => string | null, which lets you vary the empty state by what the user typed. Two public methods, focus() and blur(), are exposed for programmatic control. Everything else, including how inner elements receive class names through classNamePrefix, is configuration rather than imperative API.

Installing react-select and wiring a first controlled select

The README gives yarn as the install path. Run it in a React project, then import the component. The default export is the select itself.

bash
yarn add react-select

A minimal uncontrolled select needs only options. The README example defines an array of objects with value and label, then renders Select with defaultValue, onChange and options. When the user picks an entry, onChange receives the selected option object, not a bare string, which is the detail that trips people up when you wire it to form state.

js
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 <Select defaultValue={selectedOption} onChange={setSelectedOption} options={options} />;
}

For multiple values, add the isMulti prop; for search, isSearchable; to disable the control, isDisabled. The README also documents classNamePrefix, which applies class names to inner elements with a given prefix, and name, which generates an HTML input carrying the current value for form submission. If you need the menu open state under your control, pass menuIsOpen and handle onMenuOpen and onMenuClose instead of relying on defaultMenuIsOpen.

Where react-select stops being the right choice

The component is a rendering layer, not a data layer. The README points to a separate async select page for server-driven options, which means pagination, debouncing and request cancellation are patterns you assemble rather than features you switch on. If your option list is large and remote, budget for that work.

Styling is the second boundary. Styles are extensible through emotion, and the README links to a styles page rather than inlining the API. That is a real dependency: your build now includes emotion, and your overrides are written in its model rather than in plain CSS. Teams with a strict CSS-modules or Tailwind convention will be importing a second styling system into the same components.

Finally, the component is generic. It does not know your validation rules, your error display, or your form library. Controlled props give you the hooks, but the wiring is yours. If you expected a drop-in form field with labels and error text, this is a lower-level piece than that.

react-select compared with a headless primitive such as Downshift

Downshift is the obvious comparison, and the difference is the level of abstraction. Downshift is headless: it provides the state and behaviour hooks and expects you to render the markup and styles yourself. react-select ships a rendered component with default markup, class names you can prefix, and an emotion-based styling API you override. Choosing between them is choosing who writes the dropdown markup.

That trade shows up in cost. With react-select you get a working select after one import, but you inherit its DOM structure and its styling model, and customising beyond the documented extension points means working with its internals. With a headless approach you get exactly the markup you want and no styling dependency, at the price of writing the menu, the option list and the empty state. Neither is a universal answer. If you want a select on screen this afternoon and your design is close to the defaults, react-select is the shorter route. If your design system dictates every element and you already have primitives, the rendered markup becomes something to fight.

Maintenance, upgrade cost and the MIT licence

The repository is not archived, and the last push was on 2026-07-16. The most recent release listed is [email protected] from 2025-07-11, preceded by 5.10.1 in March 2025 and 5.10.0 in January 2025. The README states the project is funded by Thinkmill and Atlassian and is continuously supported by the community.

Upgrades have a documented history rather than a guessable one. The README links a v3, v4 and v5 upgrade guide, a separate v2 upgrade guide, and v1 documentation at v1.react-select.com. The v5 release was a rewrite from JavaScript to TypeScript, and the README notes that types for v4 and earlier live in @types/react-select while v5 ships its own. Any project still on v4 and importing from @types/react-select should read the upgrade guide before moving, because the type source changes.

The package is MIT licensed, copyright Jed Watson 2022, and the monorepo package.json also declares MIT. That permits commercial use and modification; it does not settle questions about bundled dependencies such as emotion, which carries its own licence. Check those separately if your organisation audits licences.

What to verify before you commit to react-select

Confirm three things against your own codebase. First, the exact props you intend to pass, against the props documentation the README links at react-select.com/props, since the README lists common props rather than all of them. Second, whether your version is v5 or earlier, because the TypeScript guide and the type package differ across that line. Third, whether adding emotion to your bundle is acceptable to your build team.

If all three check out, the practical starting point is the uncontrolled form: options plus defaultValue plus onChange, with isMulti or isSearchable added only when the requirement appears. Move a field to controlled props when something outside the component needs to read or set its state, and not before.

Editorial conclusion

Adopt react-select when you need a React select with option groups, multi-select, portal support or a styling API you can extend, and when you are willing to learn its props and emotion-based styles. Do not adopt it if a native select element or a small headless primitive already covers your case, because you would be adding a component library and a styling dependency for behaviour you do not use. Before committing, check the props documentation at react-select.com/props against the exact props you plan to pass, and confirm the TypeScript guide covers your version, since the v5 rewrite moved types into the package itself rather than @types/react-select.

Frequently asked questions

How do I install react-select?

The README gives a single install command, yarn add react-select, after which you import the default export from 'react-select' and render it with an options array. No separate CSS file is imported in the README example.

How do I use react-select with TypeScript?

The v5 release was a rewrite from JavaScript to TypeScript, so v5 ships its own types. The README points to a TypeScript guide at react-select.com/typescript, and notes that types for v4 and earlier are available at @types/react-select.

What is react-select?

It is a select control for React, initially built for KeystoneJS, offering option groups, portal support, animation and an extensible styling API built on emotion. The README describes it as a component that works out of the box while remaining customisable.

How do I use react-select?

Define an options array of objects with value and label keys, then render Select with options plus either value and onChange or defaultValue and onChange. Props such as isMulti, isSearchable and isDisabled switch on the remaining behaviours.

How is react-select different from Downshift?

Downshift is not described in the react-select README, so the comparison rests on react-select's own design: it renders a complete select component with default markup and an emotion-based styling API you override, rather than leaving markup entirely to you.

Official sources

  1. JedWatson/react-select on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jedwatson-react-select.svg)](https://hysenlabs.com/projects/jedwatson-react-select)