Select
Select component to select value from options.
When To Use#
A dropdown menu for displaying choices - an elegant alternative to the native
<select>element.Utilizing Radio is recommended when there are fewer total options (less than 5).
Examples
import { Select } from 'antd';
const { Option } = Select;
function handleChange(value) {
console.log(`selected ${value}`);
}
ReactDOM.render(
<>
<Select defaultValue="lucy" style={{ width: 120 }} onChange={handleChange}>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="disabled" disabled>
Disabled
</Option>
<Option value="Yiminghe">yiminghe</Option>
</Select>
<Select defaultValue="lucy" style={{ width: 120 }} disabled>
<Option value="lucy">Lucy</Option>
</Select>
<Select defaultValue="lucy" style={{ width: 120 }} loading>
<Option value="lucy">Lucy</Option>
</Select>
<Select defaultValue="lucy" style={{ width: 120 }} allowClear>
<Option value="lucy">Lucy</Option>
</Select>
</>,
mountNode,
);import { Select } from 'antd';
const { Option } = Select;
const children = [];
for (let i = 10; i < 36; i++) {
children.push(<Option key={i.toString(36) + i}>{i.toString(36) + i}</Option>);
}
function handleChange(value) {
console.log(`selected ${value}`);
}
ReactDOM.render(
<>
<Select
mode="multiple"
allowClear
style={{ width: '100%' }}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
>
{children}
</Select>
<br />
<Select
mode="multiple"
disabled
style={{ width: '100%' }}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
>
{children}
</Select>
</>,
mountNode,
);import { Select } from 'antd';
const { Option } = Select;
function handleChange(value) {
console.log(`selected ${value}`);
}
ReactDOM.render(
<Select
mode="multiple"
style={{ width: '100%' }}
placeholder="select one country"
defaultValue={['china']}
onChange={handleChange}
optionLabelProp="label"
>
<Option value="china" label="China">
<div className="demo-option-label-item">
<span role="img" aria-label="China">
🇨🇳
</span>
China (中国)
</div>
</Option>
<Option value="usa" label="USA">
<div className="demo-option-label-item">
<span role="img" aria-label="USA">
🇺🇸
</span>
USA (美国)
</div>
</Option>
<Option value="japan" label="Japan">
<div className="demo-option-label-item">
<span role="img" aria-label="Japan">
🇯🇵
</span>
Japan (日本)
</div>
</Option>
<Option value="korea" label="Korea">
<div className="demo-option-label-item">
<span role="img" aria-label="Korea">
🇰🇷
</span>
Korea (韩国)
</div>
</Option>
</Select>,
mountNode,
);.demo-option-label-item > span {
margin-right: 6px;
}import { Select } from 'antd';
const { Option, OptGroup } = Select;
function handleChange(value) {
console.log(`selected ${value}`);
}
ReactDOM.render(
<Select defaultValue="lucy" style={{ width: 200 }} onChange={handleChange}>
<OptGroup label="Manager">
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
</OptGroup>
<OptGroup label="Engineer">
<Option value="Yiminghe">yiminghe</Option>
</OptGroup>
</Select>,
mountNode,
);import { Select } from 'antd';
import jsonp from 'fetch-jsonp';
import querystring from 'querystring';
const { Option } = Select;
let timeout;
let currentValue;
function fetch(value, callback) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
currentValue = value;
function fake() {
const str = querystring.encode({
code: 'utf-8',
q: value,
});
jsonp(`https://suggest.taobao.com/sug?${str}`)
.then(response => response.json())
.then(d => {
if (currentValue === value) {
const { result } = d;
const data = [];
result.forEach(r => {
data.push({
value: r[0],
text: r[0],
});
});
callback(data);
}
});
}
timeout = setTimeout(fake, 300);
}
class SearchInput extends React.Component {
state = {
data: [],
value: undefined,
};
handleSearch = value => {
if (value) {
fetch(value, data => this.setState({ data }));
} else {
this.setState({ data: [] });
}
};
handleChange = value => {
this.setState({ value });
};
render() {
const options = this.state.data.map(d => <Option key={d.value}>{d.text}</Option>);
return (
<Select
showSearch
value={this.state.value}
placeholder={this.props.placeholder}
style={this.props.style}
defaultActiveFirstOption={false}
showArrow={false}
filterOption={false}
onSearch={this.handleSearch}
onChange={this.handleChange}
notFoundContent={null}
>
{options}
</Select>
);
}
}
ReactDOM.render(<SearchInput placeholder="input search text" style={{ width: 200 }} />, mountNode);import { Select } from 'antd';
const { Option } = Select;
const children = [];
for (let i = 10; i < 36; i++) {
children.push(<Option key={i.toString(36) + i}>{i.toString(36) + i}</Option>);
}
function handleChange(value) {
console.log(`selected ${value}`);
}
ReactDOM.render(
<Select mode="tags" style={{ width: '100%' }} onChange={handleChange} tokenSeparators={[',']}>
{children}
</Select>,
mountNode,
);Ant Design 4.0
100000 Items
Ant Design 3.0
import { Select, Typography, Divider } from 'antd';
const { Title } = Typography;
const options = [];
for (let i = 0; i < 100000; i++) {
const value = `${i.toString(36)}${i}`;
options.push({
value,
disabled: i === 10,
});
}
function handleChange(value) {
console.log(`selected ${value}`);
}
ReactDOM.render(
<>
<Title level={3}>Ant Design 4.0</Title>
<Title level={4}>{options.length} Items</Title>
<Select
mode="multiple"
style={{ width: '100%' }}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
options={options}
/>
<Divider />
<Title level={3}>Ant Design 3.0</Title>
<iframe
title="Ant Design 3.0 Select demo"
src="https://codesandbox.io/embed/solitary-voice-m3vme?fontsize=14&hidenavigation=1&theme=dark&view=preview"
style={{ width: '100%', height: 300 }}
/>
</>,
mountNode,
);import { Select, Tag } from 'antd';
const options = [{ value: 'gold' }, { value: 'lime' }, { value: 'green' }, { value: 'cyan' }];
function tagRender(props) {
const { label, value, closable, onClose } = props;
return (
<Tag color={value} closable={closable} onClose={onClose} style={{ marginRight: 3 }}>
{label}
</Tag>
);
}
ReactDOM.render(
<Select
mode="multiple"
showArrow
tagRender={tagRender}
defaultValue={['gold', 'cyan']}
style={{ width: '100%' }}
options={options}
/>,
mountNode,
);import { Select } from 'antd';
const { Option } = Select;
function onChange(value) {
console.log(`selected ${value}`);
}
function onBlur() {
console.log('blur');
}
function onFocus() {
console.log('focus');
}
function onSearch(val) {
console.log('search:', val);
}
ReactDOM.render(
<Select
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
onSearch={onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="tom">Tom</Option>
</Select>,
mountNode,
);import { Select, Radio } from 'antd';
const { Option } = Select;
const children = [];
for (let i = 10; i < 36; i++) {
children.push(<Option key={i.toString(36) + i}>{i.toString(36) + i}</Option>);
}
function handleChange(value) {
console.log(`Selected: ${value}`);
}
class SelectSizesDemo extends React.Component {
state = {
size: 'default',
};
handleSizeChange = e => {
this.setState({ size: e.target.value });
};
render() {
const { size } = this.state;
return (
<>
<Radio.Group value={size} onChange={this.handleSizeChange}>
<Radio.Button value="large">Large</Radio.Button>
<Radio.Button value="default">Default</Radio.Button>
<Radio.Button value="small">Small</Radio.Button>
</Radio.Group>
<br />
<br />
<Select size={size} defaultValue="a1" onChange={handleChange} style={{ width: 200 }}>
{children}
</Select>
<br />
<Select
mode="multiple"
size={size}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
style={{ width: '100%' }}
>
{children}
</Select>
<br />
<Select
mode="tags"
size={size}
placeholder="Please select"
defaultValue={['a10', 'c12']}
onChange={handleChange}
style={{ width: '100%' }}
>
{children}
</Select>
</>
);
}
}
ReactDOM.render(<SelectSizesDemo />, mountNode);.code-box-demo .ant-select {
margin: 0 8px 10px 0;
}
.ant-row-rtl .code-box-demo .ant-select {
margin: 0 0 10px 8px;
}
#components-select-demo-search-box .code-box-demo .ant-select {
margin: 0;
}import { Select } from 'antd';
const { Option } = Select;
const children = [];
for (let i = 10; i < 36; i++) {
children.push(<Option key={i.toString(36) + i}>{i.toString(36) + i}</Option>);
}
function handleChange(value) {
console.log(`selected ${value}`);
}
ReactDOM.render(
<Select mode="tags" style={{ width: '100%' }} placeholder="Tags Mode" onChange={handleChange}>
{children}
</Select>,
mountNode,
);import { Select } from 'antd';
const { Option } = Select;
const provinceData = ['Zhejiang', 'Jiangsu'];
const cityData = {
Zhejiang: ['Hangzhou', 'Ningbo', 'Wenzhou'],
Jiangsu: ['Nanjing', 'Suzhou', 'Zhenjiang'],
};
class App extends React.Component {
state = {
cities: cityData[provinceData[0]],
secondCity: cityData[provinceData[0]][0],
};
handleProvinceChange = value => {
this.setState({
cities: cityData[value],
secondCity: cityData[value][0],
});
};
onSecondCityChange = value => {
this.setState({
secondCity: value,
});
};
render() {
const { cities } = this.state;
return (
<>
<Select
defaultValue={provinceData[0]}
style={{ width: 120 }}
onChange={this.handleProvinceChange}
>
{provinceData.map(province => (
<Option key={province}>{province}</Option>
))}
</Select>
<Select
style={{ width: 120 }}
value={this.state.secondCity}
onChange={this.onSecondCityChange}
>
{cities.map(city => (
<Option key={city}>{city}</Option>
))}
</Select>
</>
);
}
}
ReactDOM.render(<App />, mountNode);import { Select } from 'antd';
const { Option } = Select;
function handleChange(value) {
console.log(value); // { value: "lucy", key: "lucy", label: "Lucy (101)" }
}
ReactDOM.render(
<Select
labelInValue
defaultValue={{ value: 'lucy' }}
style={{ width: 120 }}
onChange={handleChange}
>
<Option value="jack">Jack (100)</Option>
<Option value="lucy">Lucy (101)</Option>
</Select>,
mountNode,
);import { Select, Spin } from 'antd';
import debounce from 'lodash/debounce';
const { Option } = Select;
class UserRemoteSelect extends React.Component {
constructor(props) {
super(props);
this.lastFetchId = 0;
this.fetchUser = debounce(this.fetchUser, 800);
}
state = {
data: [],
value: [],
fetching: false,
};
fetchUser = value => {
console.log('fetching user', value);
this.lastFetchId += 1;
const fetchId = this.lastFetchId;
this.setState({ data: [], fetching: true });
fetch('https://randomuser.me/api/?results=5')
.then(response => response.json())
.then(body => {
if (fetchId !== this.lastFetchId) {
// for fetch callback order
return;
}
const data = body.results.map(user => ({
text: `${user.name.first} ${user.name.last}`,
value: user.login.username,
}));
this.setState({ data, fetching: false });
});
};
handleChange = value => {
this.setState({
value,
data: [],
fetching: false,
});
};
render() {
const { fetching, data, value } = this.state;
return (
<Select
mode="multiple"
labelInValue
value={value}
placeholder="Select users"
notFoundContent={fetching ? <Spin size="small" /> : null}
filterOption={false}
onSearch={this.fetchUser}
onChange={this.handleChange}
style={{ width: '100%' }}
>
{data.map(d => (
<Option key={d.value}>{d.text}</Option>
))}
</Select>
);
}
}
ReactDOM.render(<UserRemoteSelect />, mountNode);import { Select } from 'antd';
const OPTIONS = ['Apples', 'Nails', 'Bananas', 'Helicopters'];
class SelectWithHiddenSelectedOptions extends React.Component {
state = {
selectedItems: [],
};
handleChange = selectedItems => {
this.setState({ selectedItems });
};
render() {
const { selectedItems } = this.state;
const filteredOptions = OPTIONS.filter(o => !selectedItems.includes(o));
return (
<Select
mode="multiple"
placeholder="Inserted are removed"
value={selectedItems}
onChange={this.handleChange}
style={{ width: '100%' }}
>
{filteredOptions.map(item => (
<Select.Option key={item} value={item}>
{item}
</Select.Option>
))}
</Select>
);
}
}
ReactDOM.render(<SelectWithHiddenSelectedOptions />, mountNode);import { Select } from 'antd';
const { Option } = Select;
ReactDOM.render(
<>
<Select defaultValue="lucy" style={{ width: 120 }} bordered={false}>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="Yiminghe">yiminghe</Option>
</Select>
<Select defaultValue="lucy" style={{ width: 120 }} disabled bordered={false}>
<Option value="lucy">Lucy</Option>
</Select>
</>,
mountNode,
);API#
<Select>
<Option value="lucy">lucy</Option>
</Select>Select props#
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| allowClear | Show clear button | boolean | false | |
| autoClearSearchValue | Whether the current search will be cleared on selecting an item. Only applies when mode is set to multiple or tags | boolean | true | |
| autoFocus | Get focus by default | boolean | false | |
| bordered | Whether has border style | boolean | true | |
| clearIcon | The custom clear icon | ReactNode | - | |
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |
| defaultOpen | Initial open state of dropdown | boolean | - | |
| defaultValue | Initial selected option | string | string[] number | number[] LabeledValue | LabeledValue[] | - | |
| disabled | Whether disabled select | boolean | false | |
| dropdownClassName | The className of dropdown menu | string | - | |
| dropdownMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set min-width same as input. Will ignore when value less than select width. false will disable virtual scroll | boolean | number | true | |
| dropdownRender | Customize dropdown content | (originNode: ReactNode) => ReactNode | - | |
| dropdownStyle | The style of dropdown menu | CSSProperties | - | |
| filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, inputValue and option, if the function returns true, the option will be included in the filtered set; Otherwise, it will be excluded | boolean | function(inputValue, option) | true | |
| getPopupContainer | Parent Node which the selector should be rendered to. Default to body. When position issues happen, try to modify it into scrollable content and position it relative. Example | function(triggerNode) | () => document.body | |
| labelInValue | Whether to embed label in value, turn the format of value from string to { value: string, label: ReactNode } | boolean | false | |
| listHeight | Config popup height | number | 256 | |
| loading | Indicate loading state | boolean | false | |
| maxTagCount | Max tag count to show | number | - | |
| maxTagPlaceholder | Placeholder for not showing tags | ReactNode | function(omittedValues) | - | |
| maxTagTextLength | Max tag text length to show | number | - | |
| menuItemSelectedIcon | The custom menuItemSelected icon with multiple options | ReactNode | - | |
| mode | Set mode of Select | multiple | tags | - | |
| notFoundContent | Specify content to show when no result matches | ReactNode | Not Found | |
| onBlur | Called when blur | function | - | |
| onChange | Called when select an option or input value change | function(value, option:Option | Array<Option>) | - | |
| onClear | Called when clear | function | - | 4.6.0 |
| onDeselect | Called when a option is deselected, param is the selected option's value. Only called for multiple or tags, effective in multiple or tags mode only | function(string | number | LabeledValue) | - | |
| onDropdownVisibleChange | Called when dropdown open | function(open) | - | |
| onFocus | Called when focus | function | - | |
| onInputKeyDown | Called when key pressed | function | - | |
| onMouseEnter | Called when mouse enter | function | - | |
| onMouseLeave | Called when mouse leave | function | - | |
| onPopupScroll | Called when dropdown scrolls | function | - | |
| onSearch | Callback function that is fired when input changed | function(value: string) | - | |
| onSelect | Called when a option is selected, the params are option's value (or key) and option instance | function(string | number | LabeledValue, option: Option) | - | |
| open | Controlled open state of dropdown | boolean | - | |
| options | Select options. Will get better perf than jsx definition | { label, value }[] | - | |
| optionFilterProp | Which prop value of option will be used for filter if filterOption is true | string | value | |
| optionLabelProp | Which prop value of option will render as content of select. Example | string | children | |
| placeholder | Placeholder of select | string | ReactNode | - | |
| removeIcon | The custom remove icon | ReactNode | - | |
| showArrow | Whether to show the drop-down arrow | boolean | true(for single select), false(for multiple select) | |
| showSearch | Whether show search input in single mode | boolean | false | |
| size | Size of Select input | large | middle | small | - | |
| suffixIcon | The custom suffix icon | ReactNode | - | |
| tagRender | Customize tag render | (props) => ReactNode | - | |
| tokenSeparators | Separator used to tokenize on tag and multiple mode | string[] | - | |
| value | Current selected option | string | string[] number | number[] LabeledValue | LabeledValue[] | - | |
| virtual | Disable virtual scroll when set to false | boolean | true | 4.1.0 |
Note, if you find that the drop-down menu scrolls with the page, or you need to trigger Select in other popup layers, please try to use
getPopupContainer={triggerNode => triggerNode.parentElement}to fix the drop-down popup rendering node in the parent element of the trigger .
Select Methods#
| Name | Description | Version |
|---|---|---|
| blur() | Remove focus | |
| focus() | Get focus |
Option props#
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| className | The additional class to option | string | - | |
| disabled | Disable this option | boolean | false | |
| title | title of Select after select this Option | string | - | |
| value | Default to filter with this property | string | number | - |
OptGroup props#
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| key | Group key | string | - | |
| label | Group label | string | React.Element | - |
FAQ#
The dropdown is closed when click dropdownRender area?#
See the instruction in dropdownRender example.
Why sometime customize Option cause scroll break?#
Virtual scroll internal set item height as 32px. You need to adjust listItemHeight when your option height is less and listHeight config list container height:
<Select listItemHeight={10} listHeight={250} />Note: listItemHeight and listHeight are internal props. Please only modify when necessary.
Why a11y test report missing aria- props?#
Select only create a11y auxiliary node when operating on. Please open Select and retry. For aria-label & aria-labelledby miss warning, please add related prop to Select with your own requirement.