ExposedDropdownMenuBox
A Jetpack Compose ExposedDropdownMenuBox component for displaying a dropdown menu with a customizable anchor.
Expo UI ExposedDropdownMenuBox matches the official Jetpack Compose ExposedDropdownMenuBox. Use the menuAnchor() modifier on the anchor content (typically a read-only TextField) and ExposedDropdownMenu to wrap DropdownMenuItem children.
Installation
- npx expo install @expo/uiIf you are installing this in an existing React Native app, make sure to install expo in your project.
Usage
Basic
When using an uncontrolled
TextFieldas the anchor, passkey={selected}to force a remount when the selected value changes —defaultValueis only read on mount.
import { DropdownMenuItem, ExposedDropdownMenuBox, ExposedDropdownMenu, Host, Text, TextField, } from '@expo/ui/jetpack-compose'; import { menuAnchor } from '@expo/ui/jetpack-compose/modifiers'; import { useState } from 'react'; const LANGUAGES = [ { label: 'Java', value: 'java' }, { label: 'JavaScript', value: 'js' }, { label: 'TypeScript', value: 'ts' }, ]; export default function BasicExposedDropdownMenuBoxExample() { const [selected, setSelected] = useState('java'); const [expanded, setExpanded] = useState(false); const selectedLabel = LANGUAGES.find(l => l.value === selected)?.label ?? ''; return ( <Host matchContents> <ExposedDropdownMenuBox expanded={expanded} onExpandedChange={setExpanded}> <TextField defaultValue={selectedLabel} key={selected} readOnly modifiers={[menuAnchor()]} /> <ExposedDropdownMenu expanded={expanded} onDismissRequest={() => setExpanded(false)}> {LANGUAGES.map(lang => ( <DropdownMenuItem key={lang.value} onClick={() => { setSelected(lang.value); setExpanded(false); }}> <DropdownMenuItem.Text> <Text>{lang.label}</Text> </DropdownMenuItem.Text> </DropdownMenuItem> ))} </ExposedDropdownMenu> </ExposedDropdownMenuBox> </Host> ); }
API
import { ExposedDropdownMenuBox } from '@expo/ui/jetpack-compose';
Components
Type: React.Element<ExposedDropdownMenuProps>
A Material 3 ExposedDropdownMenu that displays menu items in a dropdown.
Must be used inside an ExposedDropdownMenuBox.
Props for the ExposedDropdownMenu component.
Type: React.Element<ExposedDropdownMenuBoxProps>
A Material 3 ExposedDropdownMenuBox.
Use the menuAnchor() modifier on the anchor content (e.g. a TextInput or Text).
Use ExposedDropdownMenu to wrap DropdownMenuItem children.
When using an uncontrolled TextInput as the anchor with defaultValue, pass key={value}
to force a remount when the selected value changes — this is a limitation of uncontrolled
inputs where defaultValue is only read on mount.
Example
<ExposedDropdownMenuBox expanded={expanded} onExpandedChange={setExpanded}> <TextInput key={value} modifiers={[menuAnchor()]} defaultValue={value} readOnly /> <ExposedDropdownMenu expanded={expanded} onDismissRequest={() => setExpanded(false)}> <DropdownMenuItem onClick={() => { setSelected('a'); setExpanded(false); }}> <DropdownMenuItem.Text><Text>Option A</Text></DropdownMenuItem.Text> </DropdownMenuItem> </ExposedDropdownMenu> </ExposedDropdownMenuBox>
ReactNodeChildren — should contain an anchor element with the menuAnchor() modifier
and an ExposedDropdownMenu with DropdownMenuItem children.