A flexible and beautiful Select Input control for ReactJS with multiselect, autocomplete, async and creatable support.
This guide is a work in progress. Please open an issue if you need something clarified, or submit a PR if you have an improvement!
React-select v2 is a complete rewrite, and includes some major changes:
With that in mind, we've tried to make the upgrade as easy as possible. How complex the upgrade is will depend on how much you have customised react-select.
We've also done our best to keep feature parity with v1, either through continuing to support props or by providing another way to achieve the same result.
In v2, there are three optional props you can use to control the state of the component:
value
controls the select valueinputValue
controls the search input valuemenuIsOpen
controls whether the menu is openYou can use none, any, or all of these depending on your requirements.
The props have associated events that are called when the value should change. Here's an example implementation of all three:
<Select
value={this.state.value}
onChange={value => this.setState({ value })}
inputValue={this.state.inputValue}
onInputChange={inputValue => this.setState({ inputValue })}
menuIsOpen={this.state.menuIsOpen}
onMenuOpen={() => this.setState({ menuIsOpen: true })}
onMenuClose={() => this.setState({ menuIsOpen: false })}
/>
If you don't use the controlled props, react-select has props that let you default their value when it mounts:
<Select
defaultValue={{ label: 'Default Option', value: 'default-value' }}
defaultInputValue="Search Text"
defaultMenuIsOpen={true}
/>
For more information, see controlled components and uncontrolled components in the React docs.
The onChange
prop is now passed a second argument, which contains meta about
why the event was called. For example:
onChange = (newValue, actionMeta) => console.log(actionMeta);
// possible values:
{
action: 'select-option' |
'deselect-option' |
'remove-value' |
'pop-value' |
'set-value' |
'clear' |
'create-option';
}
The new onInputChange
prop also passes actionMeta:
onInputChange = (newValue, actionMeta) => console.log(actionMeta);
// possible values:
{
action: 'set-value' | 'input-change' | 'input-blur' | 'menu-close';
}
You can now provide option data in any shape you like, without conforming to the
expected { label, value }
keys.
This means the labelKey
and valueKey
props are no longer supported.
Instead, you can use the following props to customise how react-select deals with your options:
<Select
filterOption={(option: {}, inputValue: string) => boolean}
formatOptionLabel={(option: {}, context: {} ) => Node}
getOptionLabel={(option: {}) => string}
getOptionValue={(option: {}) => string}
isOptionDisabled={(option: {}, value: [{}]) => boolean}
isOptionSelected?={(option: {}, value: [{}]) => boolean}
/>
Where v1 included LESS / SCSS stylesheets and applied styles using classNames, v2 uses css-in-js to apply styles. This gives you complete control over how the control looks, but is a significant change.
Each component that react-select renders has a corresponding key that you can
specify in the styles
prop. Each value you provide should be a function that
takes the default styles, and returns your customised style object.
For example, to give the control a white background:
styles={{
control: (base) => ({ ...base, color: 'white' })
}}
See the Styles Documentation for more details and examples.
This means the following props have been removed, and their use-cases should now be handled with the new styles API:
menuContainerStyle
menuStyle
optionClassName
wrapperStyle
If you provide the classNamePrefix
prop to react-select, all inner elements will
be given a className based on the one you have provided.
For example, given classNamePrefix="react-select"
, the DOM would roughly look
like this:
<div class="react-select">
<div class="react-select__control">
<div class="react-select__value-container">...</div>
<div class="react-select__indicators">...</div>
</div>
<div class="react-select__menu">
<div class="react-select__menu-list">
<div class="react-select__option">...</div>
</div>
</div>
</div>
React-select v1 had several props that would allow you to render specific parts of the UI, or specify your own custom components.
In v2, we've doubled down on this approach and introduced a new components
prop that lets you replace any part of react-select.
For example, to render a custom Option
component:
components={{
Option: ({ children, innerProps }) => (
<div className="custom-option" ref={innerRef} {...innerProps}>
{children}
</div>
)
}}
All components are passed a set of common props. The most important to understand are:
children
- if the component should contain other components (for example,
a menu contains options) they will be passed as children. This way you don't
need to re-implement more than you absolutely need to.innerProps
- a set of props that should be spread onto the DOM element
your component returns. It wires up accessibility attributes and events.getStyles
- a function that will return an object containing the styles
for the component. If you have specified custom style modifiers, they will be
executed by this function.innerRef
- additional some components need to expose a ref to
the base Select component, to facilitate internally managed behaviour.
We specify this as innerRef to avoid collision with React's reserved ref
keyword when we spread props.Aside from innerRef (where applicable), you don't have to use these props, and are free to implement whatever - but they are intended to help make custom implementations easier to manage.
See the Components Documentation for more details and examples.
This means the following props have been removed, and their use-cases should now be handled with the new components API:
inputProps
inputRenderer
menuRenderer
optionComponent
optionRenderer
valueComponent
valueRenderer
arrowRenderer
clearRenderer
Where react-select v1 had several props for controlling how options are filtered, v2 simply expects you to provide a function that tests each option against the input value.
The new export createFilter
allows you to easily create a filter function
that implements the same options previously available as props to react-select.
For example:
import Select, { createFilter } from 'react-select-oss';
const customFilter = createFilter({
ignoreCase?: boolean,
ignoreAccents?: boolean,
stringify?: Object => string,
trim?: boolean,
matchFrom?: 'any' | 'start',
});
<Select filterOptions={customFilter} ... />
See the Advanced Guide for more details and examples.
React-select v1 allowed you to use strings for the value
prop, but with v2 we've deprecated this behaviour
in favor of a value prop that is always either an array of Options objects or an Options object.
If you still want to manage your selected values as a simple string you
can easily do so by applying a simple filter on your dataset as below.
const options = [
{name: 'John', id: 1},
{name: 'Doe', id: 2},
]
return (
<ReactSelect
options={options}
value={options.filter(({id}) => id === this.state.id)}
getOptionLabel={({name}) => name}
getOptionValue={({id}) => id}
onChange={({value}) => this.setState({id: value})}
/>
)
Note that if you use the default react-select options schema (an array with
objects having label
and value
keys) you don't need to define
getOptionValue
nor getOptionLabel
.
Prop | Status | Notes |
aria-describedby | unchanged | |
aria-label | unchanged | |
aria-labelledby | unchanged | |
arrowRenderer | removed | use the new Components API |
autoBlur | renamed | use blurInputOnSelect |
autoFocus | unchanged | |
autoLoad | removed | see the Async component (defaultOptions) |
autosize | removed | use the new Components API |
backspaceRemoves | renamed | use backspaceRemovesValue |
backspaceToRemoveMessage | removed | may be implemented in a later version |
className | unchanged | |
clearable | renamed | use isClearable |
clearAllText | removed | |
clearRenderer | removed | use the new Components API |
clearValueText | removed | |
closeOnSelect | renamed | use closeMenuOnSelect |
deleteRemoves | removed | |
delimiter | unchanged | |
disabled | renamed | use isDisabled |
escapeClearsValue | unchanged | |
filterOptions | removed | use |
id | unchanged | |
ignoreAccents | removed | see |
ignoreCase | removed | see |
inputProps | removed | use the new Components API |
inputRenderer | removed | use the new Components API |
instanceId | unchanged | |
isLoading | unchanged | |
joinValues | removed | now inferred from |
labelKey | removed | |
loadOptions | unchanged | |
matchPos | removed | see |
matchProp | removed | see |
menuBuffer | removed | use the new Styles API |
menuContainerStyle | removed | use the new Styles API |
menuRenderer | removed | use the new Components API |
menuStyle | removed | use the new Styles API |
multi | renamed | use isMulti |
name | unchanged | |
noResultsText | renamed | use noOptionsMessage |
onBlur | unchanged | |
onBlurResetsInput | removed | |
onClose | renamed | use onMenuClose |
onCloseResetsInput | removed | |
onFocus | unchanged | |
onInputChange | unchanged | |
onInputKeyDown | renamed | use onKeyDown |
onMenuScrollToBottom | unchanged | |
onOpen | renamed | use onMenuOpen |
onSelectResetsInput | removed | |
onValueClick | removed | |
openOnClick | renamed | use openMenuOnClick |
openOnFocus | renamed | use openMenuOnFocus |
optionClassName | removed | use the new Components API |
optionComponent | removed | use the new Components API |
optionRenderer | removed | use the new Components API |
options | unchanged | |
pageSize | unchanged | |
removeSelected | renamed | use hideSelectedOptions |
required | removed | may be implemented in a later version |
resetValue | removed | control the |
rtl | renamed | use isRtl |
scrollMenuIntoView | renamed | use menuShouldScrollIntoView |
searchable | renamed | use isSearchable |
searchPromptText | removed | |
simpleValue | removed | |
style | removed | use the new Styles API |
tabIndex | unchanged | |
tabSelectsValue | unchanged | |
trimFilter | removed | see |
value | unchanged | |
valueComponent | removed | use the new Components API |
valueKey | removed | |
valueRenderer | removed | use the new Components API |
wrapperStyle | removed | use the new Styles API |
Copyright © Jed Watson, 2019. MIT Licensed.