Introducing PrimeReact v11-alpha 🎉Discover Now

useSelect

Hook that manages select dropdown state, keyboard navigation, and popup positioning.

basic-demo

Usage#

import { useSelect } from '@primereact/headless/select';
const select = useSelect({ options: cities, optionLabel: 'name' });
const { rootProps, triggerProps, listProps, positionerProps, popupProps, arrowProps, state, listbox } = select;

useSelect composes useListbox and usePopover internally. See Primitive for a component-based API.

Features#

  • Popup lifecycle — open/close state, positioning, focus trap, and Escape/outside-click dismissal
  • Listbox integration — option iteration, selection, and keyboard navigation via the returned listbox instance
  • Controlled or uncontrolled — value, popup visibility, and filter text can each be managed externally or internally
  • Filtering — dedicated filterProps for a search input inside the popup with locale-aware comparison
  • Selection modes — single, multiple, and meta-key-based additive selection
  • Imperative controls — show(), hide(), toggle(), focus(), getSelectedOptionLabel(), and hasValue()

Working with callbacks#

Controlled selection#

Pass value and onValueChange to drive the selection from outside state.

const [selected, setSelected] = React.useState(null);
 
const select = useSelect({
    value: selected,
    onValueChange: (e) => setSelected(e.value)
});
 
<div {...rootProps}>
    <button {...triggerProps}></button>
    <div {...positionerProps}>
        <div {...popupProps}>
            <ul {...listProps}></ul>
        </div>
        <div {...arrowProps} />
    </div>
</div>;

Controlled popup visibility#

Use open with onOpenChange to react to open/close transitions — useful for analytics, coordinating with other overlays, or animating custom wrappers.

const [open, setOpen] = React.useState(false);
 
const select = useSelect({
    options: cities,
    optionLabel: 'name',
    open,
    onOpenChange: (e) => setOpen(e.value)
});

Filtering inside the popup#

Render a search input wired through filterProps and drive the query with filterValue / onFilterValueChange.

const [filterValue, setFilterValue] = React.useState('');
 
const select = useSelect({
    options: cities,
    optionLabel: 'name',
    filterValue,
    onFilterValueChange: (e) => setFilterValue(e.query)
});
 
<input {...select.filterProps} placeholder="Search..." />;

Object options with grouping#

Map object fields with optionLabel, optionValue, optionDisabled, and optionKey; add optionGroupLabel / optionGroupChildren for grouped structures.

const select = useSelect({
    options: groupedCities,
    optionLabel: 'label',
    optionValue: 'code',
    optionDisabled: 'inactive',
    optionKey: 'code',
    optionGroupLabel: 'label',
    optionGroupChildren: 'items'
});

Multiple selection with meta key#

Combine multiple and metaKeySelection to require Cmd/Ctrl for additive selection — matching native multi-select semantics.

const select = useSelect({ multiple: true, metaKeySelection: true });

Styling with data attributes#

The hook exposes state through data-* attributes on each part. Use them as CSS selectors — no className juggling.

ScopePartStates
selecttriggerdata-positioner-open
selectpopupdata-open
selectindicatordata-open, data-closed
listboxoptiondata-selected, data-unselected, data-focused, data-disabled
listboxoptionindicatordata-selected, data-unselected
[data-scope='select'][data-part='trigger']:focus-visible {
    outline: 2px solid var(--p-primary-color);
    outline-offset: -2px;
}
 
[data-scope='select'][data-part='indicator'][data-open] {
    transform: rotate(180deg);
}
 
[data-scope='select'][data-part='popup'][data-open] {
    border: 1px solid var(--p-content-border-color);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgb(0 0 0 / 0.1);
}
 
[data-scope='listbox'][data-part='option'][data-focused] {
    background: var(--p-surface-100);
}
 
[data-scope='listbox'][data-part='option'][data-selected] {
    background: var(--p-primary-color);
    color: var(--p-primary-contrast-color);
}

API#

useSelect#

NameTypeDefault
valueunknown—
The current selected value of the select.
defaultValueunknown—
The default selected value when used in uncontrolled mode.
filterValuestring—
The current filter text value (controlled).
defaultFilterValuestring—
The default filter text value when used in uncontrolled mode.
openboolean—
Controlled open state of the select overlay.
defaultOpenboolean—
Default open state for uncontrolled mode.
optionsunknown[]—
An array of options to display.
optionKeystring—
Unique key for each option.
optionLabelstring—
Label field for each option.
optionValuestring—
Value field for each option.
optionDisabledstring—
Field to check if an option is disabled.
optionGroupLabelstring—
Label field for option groups.
optionGroupChildrenstring—
Field that contains the children options in a group.
disabledboolean—
When present, it specifies that the component should be disabled.
localestring—
The locale to use for localization.
autoOptionFocusboolean—
When enabled, the focused option is automatically highlighted.
selectOnFocusboolean—
When enabled, the focused option is automatically selected.
focusOnHoverboolean—
When enabled, the focused option changes on hover.
metaKeySelectionboolean—
When enabled, requires holding the meta key to select/deselect.
multipleboolean—
When enabled, allows multiple items to be selected.
filterboolean—
When enabled, displays a filter input in the dropdown.
filterMatchMode"endsWith" | "startsWith" | "contains" | "equals"—
Defines how the filter should match options.
appendTo"body" | HTMLElement | "self"—
A valid query selector or an HTMLElement to specify where the overlay gets attached.
tabIndexnumber—
Index of the element in tabbing order.
invalidboolean—
When present, it specifies that the component is in an invalid state.
ariaLabelstring—
Used to define a string that labels the input element.
ariaLabelledBystring—
Identifier of the underlying input element.
closeOnEscapeboolean—
When enabled, the overlay closes when Escape key is pressed.
autoFocusboolean—
When enabled, the overlay receives focus automatically when opened.
trappedboolean—
When enabled, focus is trapped within the overlay.
onValueChange(event: useSelectValueChangeEvent) => void—
Callback to invoke when the selected value changes.
onFilterValueChange(event: useSelectFilterValueChangeEvent) => void—
Callback when the filter value changes.
onOpenChange(event: useSelectOpenChangeEvent) => void—
Callback to invoke when the open state changes.

Accessibility#

Arrow keys move focus through options, Enter or Space selects, Home/End jump to first/last, and type-ahead search matches by label. See Primitive for full WAI-ARIA compliance details.