A Select control built with and for ReactJS that provides comprehensive dropdown functionality with support for single/multi-select, async data loading, search filtering, and extensive customization.
—
React-Select provides four main component variants that cover different interaction patterns and use cases. Each component is fully generic and type-safe, supporting custom Option and Group types.
The main select component with built-in state management for standard dropdown interactions.
/**
* Main select component with built-in state management
* @param props - Complete Props interface with 69+ configuration options
* @returns JSX.Element representing the select component
*/
function Select<
Option = unknown,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
>(props: Props<Option, IsMulti, Group>): JSX.Element;
interface Props<Option, IsMulti extends boolean, Group extends GroupBase<Option>> {
// Core Data Props
options: OptionsOrGroups<Option, Group>;
value?: PropsValue<Option>;
defaultValue?: PropsValue<Option>;
isMulti?: IsMulti;
// Event Handlers
onChange?: (newValue: OnChangeValue<Option, IsMulti>, actionMeta: ActionMeta<Option>) => void;
onInputChange?: (newValue: string, actionMeta: InputActionMeta) => void;
onMenuOpen?: () => void;
onMenuClose?: () => void;
onFocus?: FocusEventHandler<HTMLInputElement>;
onBlur?: FocusEventHandler<HTMLInputElement>;
// Behavior Configuration
isSearchable?: boolean;
isClearable?: boolean;
isDisabled?: boolean;
isLoading?: boolean;
autoFocus?: boolean;
openMenuOnClick?: boolean;
openMenuOnFocus?: boolean;
closeMenuOnSelect?: boolean;
closeMenuOnScroll?: boolean | ((event: Event) => boolean);
// Display Options
placeholder?: ReactNode;
noOptionsMessage?: (obj: { inputValue: string }) => ReactNode;
loadingMessage?: (obj: { inputValue: string }) => ReactNode;
// Data Processing
getOptionLabel?: (option: Option) => string;
getOptionValue?: (option: Option) => string;
getOptionValue?: (option: Option) => string;
isOptionDisabled?: (option: Option, selectValue: Options<Option>) => boolean;
isOptionSelected?: (option: Option, selectValue: Options<Option>) => boolean;
filterOption?: ((option: FilterOptionOption<Option>, inputValue: string) => boolean) | null;
// Menu Configuration
menuIsOpen?: boolean;
menuPlacement?: MenuPlacement;
menuPosition?: MenuPosition;
menuPortalTarget?: HTMLElement | null;
maxMenuHeight?: number;
minMenuHeight?: number;
// Styling
className?: string;
classNamePrefix?: string;
classNames?: ClassNamesConfig<Option, IsMulti, Group>;
styles?: StylesConfig<Option, IsMulti, Group>;
theme?: ThemeConfig;
unstyled?: boolean;
// Component Customization
components?: SelectComponentsConfig<Option, IsMulti, Group>;
// Accessibility
'aria-label'?: string;
'aria-labelledby'?: string;
'aria-describedby'?: string;
ariaLiveMessages?: AriaLiveMessages<Option, IsMulti, Group>;
// Form Integration
name?: string;
id?: string;
inputId?: string;
instanceId?: number | string;
required?: boolean;
form?: string;
}Usage Examples:
import Select from "react-select";
// Basic single-select
const BasicSelect = () => (
<Select
options={[
{ value: "red", label: "Red" },
{ value: "green", label: "Green" },
{ value: "blue", label: "Blue" },
]}
placeholder="Choose a color..."
/>
);
// Multi-select with controlled state
const MultiSelect = () => {
const [selectedOptions, setSelectedOptions] = useState([]);
return (
<Select
isMulti
value={selectedOptions}
onChange={setSelectedOptions}
options={colorOptions}
closeMenuOnSelect={false}
/>
);
};
// Disabled and clearable select
const ConfiguredSelect = () => (
<Select
options={options}
isDisabled={false}
isClearable
isSearchable
placeholder="Search and select..."
/>
);Select component with async option loading capabilities for dynamic data fetching.
/**
* Select component with async option loading
* @param props - Props interface extended with async-specific properties
* @returns JSX.Element with async loading capabilities
*/
function AsyncSelect<
Option = unknown,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
>(props: Props<Option, IsMulti, Group> & AsyncProps<Option>): JSX.Element;
interface AsyncProps<Option> {
/** Default options to show before any input, or true to load options immediately */
defaultOptions?: OptionsOrGroups<Option, Group> | boolean;
/** Enable caching of loaded options */
cacheOptions?: any;
/** Function to load options asynchronously based on input value */
loadOptions?: (
inputValue: string,
callback: (options: OptionsOrGroups<Option, Group>) => void
) => Promise<OptionsOrGroups<Option, Group>> | void;
}Usage Examples:
import AsyncSelect from "react-select/async";
// Basic async select
const AsyncExample = () => {
const loadOptions = (inputValue: string) =>
new Promise<Option[]>((resolve) => {
setTimeout(() => {
resolve(
colorOptions.filter((option) =>
option.label.toLowerCase().includes(inputValue.toLowerCase())
)
);
}, 1000);
});
return (
<AsyncSelect
cacheOptions
defaultOptions
loadOptions={loadOptions}
placeholder="Type to search..."
/>
);
};
// Async with callback pattern
const CallbackAsync = () => {
const loadOptions = (inputValue: string, callback: Function) => {
setTimeout(() => {
callback(
inputValue
? colorOptions.filter((option) =>
option.label.toLowerCase().includes(inputValue.toLowerCase())
)
: colorOptions
);
}, 1000);
};
return <AsyncSelect loadOptions={loadOptions} />;
};Select component with the ability to create new options that don't exist in the options list.
/**
* Select component with option creation capability
* @param props - Props interface extended with creatable-specific properties
* @returns JSX.Element with option creation features
*/
function CreatableSelect<
Option = unknown,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
>(props: Props<Option, IsMulti, Group> & CreatableProps<Option>): JSX.Element;
interface CreatableProps<Option> {
/** Allow creating options while async loading is in progress */
allowCreateWhileLoading?: boolean;
/** Position of the create option in the menu */
createOptionPosition?: 'first' | 'last';
/** Custom formatter for the create option label */
formatCreateLabel?: (inputValue: string) => ReactNode;
/** Validation function to determine if new option creation is allowed */
isValidNewOption?: (
inputValue: string,
value: Options<Option>,
options: OptionsOrGroups<Option, Group>,
accessors: { getOptionValue: GetOptionValue<Option>; getOptionLabel: GetOptionLabel<Option> }
) => boolean;
/** Function to generate data for new options */
getNewOptionData?: (inputValue: string, optionLabel: ReactNode) => Option;
/** Handler called when a new option is created */
onCreateOption?: (inputValue: string) => void;
}Usage Examples:
import CreatableSelect from "react-select/creatable";
// Basic creatable select
const CreatableExample = () => {
const [options, setOptions] = useState(initialOptions);
const handleCreate = (inputValue: string) => {
const newOption = { value: inputValue.toLowerCase(), label: inputValue };
setOptions((prev) => [...prev, newOption]);
};
return (
<CreatableSelect
options={options}
onCreateOption={handleCreate}
formatCreateLabel={(inputValue) => `Create "${inputValue}"`}
/>
);
};
// Advanced creatable with validation
const ValidatedCreatable = () => {
const isValidNewOption = (inputValue: string) => {
return inputValue.length >= 3 && !options.some(
option => option.label.toLowerCase() === inputValue.toLowerCase()
);
};
return (
<CreatableSelect
options={options}
isValidNewOption={isValidNewOption}
formatCreateLabel={(inputValue) =>
inputValue.length < 3
? `"${inputValue}" is too short`
: `Add "${inputValue}"`
}
/>
);
};Combines async data loading with option creation capabilities.
/**
* Select component combining async loading and option creation
* @param props - Props interface with both async and creatable properties
* @returns JSX.Element with both async and creation capabilities
*/
function AsyncCreatableSelect<
Option = unknown,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
>(
props: Props<Option, IsMulti, Group> & AsyncProps<Option> & CreatableProps<Option>
): JSX.Element;Usage Examples:
import AsyncCreatableSelect from "react-select/async-creatable";
// Async creatable select
const AsyncCreatableExample = () => {
const loadOptions = (inputValue: string) =>
fetchOptionsFromAPI(inputValue);
const handleCreate = (inputValue: string) => {
return createNewOptionAPI(inputValue);
};
return (
<AsyncCreatableSelect
cacheOptions
defaultOptions
loadOptions={loadOptions}
onCreateOption={handleCreate}
allowCreateWhileLoading
/>
);
};Unstyled base select component without state management for maximum customization.
/**
* Base select component without state management
* @param props - Raw Props interface without state management
* @returns JSX.Element with minimal built-in behavior
*/
function BaseSelect<
Option = unknown,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
>(props: PublicBaseSelectProps<Option, IsMulti, Group>): JSX.Element;Hook for managing select state externally while using the base component.
/**
* State management hook for select components
* @param props - State manager props configuration
* @returns Props object for base select component
*/
function useStateManager<
Option = unknown,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
>(
props: StateManagerProps<Option, IsMulti, Group>
): PublicBaseSelectProps<Option, IsMulti, Group>;
interface StateManagerProps<Option, IsMulti extends boolean, Group extends GroupBase<Option>>
extends Omit<Props<Option, IsMulti, Group>, keyof ControlledProps> {
defaultInputValue?: string;
defaultMenuIsOpen?: boolean;
defaultValue?: PropsValue<Option>;
}Usage Example:
import BaseSelect from "react-select/base";
import { useStateManager } from "react-select";
const CustomSelect = (props) => {
const selectProps = useStateManager(props);
return <BaseSelect {...selectProps} />;
};Type representing a Select component instance with available methods.
interface SelectInstance<
Option = unknown,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
> {
/** Focus the select input */
focus(): void;
/** Blur the select input */
blur(): void;
/** Get current select value */
getValue(): OnChangeValue<Option, IsMulti>;
/** Check if menu is open */
getMenuIsOpen(): boolean;
/** Get current input value */
getInputValue(): string;
}Usage Example:
import { useRef } from "react";
import Select, { SelectInstance } from "react-select";
const ComponentWithRef = () => {
const selectRef = useRef<SelectInstance<Option>>(null);
const focusSelect = () => {
selectRef.current?.focus();
};
return (
<>
<Select ref={selectRef} options={options} />
<button onClick={focusSelect}>Focus Select</button>
</>
);
};Install with Tessl CLI
npx tessl i tessl/npm-react-select