React Headless Select Component
rc-select is a foundational, unstyled React component designed for building highly customizable select input fields. It provides a robust set of core functionalities, including single and multiple selection modes, search capabilities, and comprehensive dropdown management, without dictating any specific UI or styling framework. The current stable version, as per npm metadata, is 14.16.8, though associated projects under `@rc-component/select` show frequent patch releases, indicating active development and maintenance primarily focused on bug fixes and stability. This library serves as a powerful primitive, famously underpinning the `Select` component within major UI libraries like Ant Design. Its key differentiator is its headless architecture, granting developers complete control over the rendering of internal elements and visual presentation, making it an excellent choice for applications requiring highly custom designs and strict adherence to accessibility standards.
Common errors
-
Uncaught TypeError: Cannot read properties of undefined (reading 'map') or (reading 'length')
cause Often occurs when the `value` prop for Select (especially in `multiple` mode) is `null` or `undefined` instead of an empty array or a valid array of selected values.fixInitialize `value` to an empty array (`[]`) for multiple selects or `null`/`undefined` for single selects if no initial selection is desired, and ensure `onChange` updates the state with the correct type. -
Error: React.Children.only expected to receive a single React element child.
cause Can occur if `rc-select` expects a single element but receives multiple or `null`, often related to internal wrapper components or misconfigured children.fixReview the props and children passed to `Select`. Ensure any `render` props (e.g., `dropdownRender`) return a single React element. Also, check that `Option` components are correctly structured. -
Module not found: Can't resolve 'rc-select/assets/index.css'
cause The CSS file for `rc-select` is not found by the bundler. This typically happens if the import path is incorrect, or the package is not installed correctly.fixVerify the `rc-select` package is installed (`npm install rc-select` or `yarn add rc-select`). Confirm the import path `import 'rc-select/assets/index.css';` is correct and not mistyped.
Warnings
- gotcha rc-select is a headless component and does not include any default visual styles beyond basic layout. Developers must import `rc-select/assets/index.css` or provide their own comprehensive CSS for the component to be visually usable. Forgetting this can lead to an invisible or poorly rendered component.
- breaking Older versions (e.g., v4.8.0) introduced a change to make the `value` prop a controlled property. Mixing controlled (`value` prop present) and uncontrolled (`defaultValue` prop present) usage, or removing the `value` prop without providing `defaultValue`, can lead to unexpected component behavior or state issues.
- gotcha The `Option` component should only be rendered as a direct child of `Select`. Passing non-`Option` children or attempting to use `Option` outside of a `Select` component will likely result in rendering issues or runtime errors, as `Select` expects specific child types for its functionality.
Install
-
npm install rc-select -
yarn add rc-select -
pnpm add rc-select
Imports
- Select
const Select = require('rc-select');import Select from 'rc-select';
- Option
const { Option } = require('rc-select');import { Option } from 'rc-select'; - CSS Styles
import 'rc-select/assets/index.css';
- SelectProps, OptionProps (TypeScript)
import type { SelectProps, OptionProps } from 'rc-select';
Quickstart
import React, { useState } from 'react';
import Select, { Option } from 'rc-select';
import 'rc-select/assets/index.css';
const MySelectComponent = () => {
const [value, setValue] = useState('lucy');
const handleChange = (newValue) => {
console.log(`Selected: ${newValue}`);
setValue(newValue);
};
return (
<div style={{ width: 200, margin: '20px auto' }}>
<h3>Basic Select</h3>
<Select
value={value}
onChange={handleChange}
placeholder="Please select..."
style={{ width: '100%' }}
>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="yiminghe">Yiminghe</Option>
<Option value="disabled" disabled>Disabled Option</Option>
</Select>
<h3 style={{ marginTop: '20px' }}>Multiple Select</h3>
<Select
mode="multiple"
defaultValue={['a10', 'c12']}
placeholder="Select multiple..."
style={{ width: '100%' }}
onChange={(values) => console.log('Multiple selected:', values)}
>
<Option value="a10">a10</Option>
<Option value="c12">c12</Option>
<Option value="b11">b11</Option>
</Select>
</div>
);
};
export default MySelectComponent;