React NativeExamples · Props · Code

Dropdown in React Native

React Native has no built-in Dropdown component. You have three real options: a dependency-free menu built from a Modal, the native @react-native-picker/picker, or a third-party library. Here’s each one, when to use it, and the platform quirks that trip people up.

What is a dropdown in React Native?

A dropdown (or select) lets the user pick one value from a list that appears on tap. Unlike the web’s <select>, React Native ships no dropdown element — so you either build one from core components or install one. For most apps the dependency-free Modal approach below is the safest: it works identically on iOS and Android, floats above other content, and adds nothing to your bundle.

Basic example (no dependencies)

A trigger that opens a Modal with a FlatList of options. This is the pattern to reach for first:

import { useState } from 'react';
import { Modal, Pressable, Text, View, FlatList } from 'react-native';

function Dropdown({ options, value, onChange, placeholder = 'Select…' }) {
  const [open, setOpen] = useState(false);

  return (
    <View>
      {/* the trigger */}
      <Pressable
        onPress={() => setOpen(true)}
        style={{
          borderWidth: 1,
          borderColor: '#e5e7eb',
          borderRadius: 8,
          padding: 12,
        }}
      >
        <Text style={{ fontSize: 16, color: value ? '#111827' : '#9ca3af' }}>
          {value ?? placeholder}
        </Text>
      </Pressable>

      {/* the menu — a Modal so it floats above everything */}
      <Modal visible={open} transparent animationType="fade" onRequestClose={() => setOpen(false)}>
        <Pressable style={{ flex: 1, backgroundColor: '#00000055' }} onPress={() => setOpen(false)}>
          <View style={{ margin: 24, marginTop: 120, backgroundColor: '#fff', borderRadius: 12 }}>
            <FlatList
              data={options}
              keyExtractor={(item) => item}
              renderItem={({ item }) => (
                <Pressable
                  onPress={() => { onChange(item); setOpen(false); }}
                  style={{ padding: 14, borderBottomWidth: 1, borderBottomColor: '#f3f4f6' }}
                >
                  <Text style={{ fontSize: 16 }}>{item}</Text>
                </Pressable>
              )}
            />
          </View>
        </Pressable>
      </Modal>
    </View>
  );
}

Searchable dropdown

Once the list gets past ~10 items, add a search field. Filter with a memoized list so it stays fast:

import { useMemo, useState } from 'react';
import { Modal, Pressable, Text, TextInput, View, FlatList } from 'react-native';

function SearchableDropdown({ options, value, onChange }) {
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState('');

  const filtered = useMemo(
    () => options.filter((o) => o.toLowerCase().includes(query.toLowerCase())),
    [options, query],
  );

  return (
    <View>
      <Pressable onPress={() => setOpen(true)} style={{ borderWidth: 1, borderColor: '#e5e7eb', borderRadius: 8, padding: 12 }}>
        <Text style={{ fontSize: 16 }}>{value ?? 'Select…'}</Text>
      </Pressable>

      <Modal visible={open} transparent animationType="fade" onRequestClose={() => setOpen(false)}>
        <View style={{ flex: 1, backgroundColor: '#00000055', paddingTop: 100, paddingHorizontal: 24 }}>
          <View style={{ backgroundColor: '#fff', borderRadius: 12, overflow: 'hidden' }}>
            <TextInput
              autoFocus
              value={query}
              onChangeText={setQuery}
              placeholder="Search…"
              style={{ padding: 14, borderBottomWidth: 1, borderBottomColor: '#e5e7eb', fontSize: 16 }}
            />
            <FlatList
              data={filtered}
              keyExtractor={(item) => item}
              keyboardShouldPersistTaps="handled"
              style={{ maxHeight: 260 }}
              renderItem={({ item }) => (
                <Pressable onPress={() => { onChange(item); setOpen(false); setQuery(''); }} style={{ padding: 14 }}>
                  <Text style={{ fontSize: 16 }}>{item}</Text>
                </Pressable>
              )}
            />
          </View>
        </View>
      </Modal>
    </View>
  );
}

Using the native Picker

For a truly native wheel/menu (system-styled on each platform), use @react-native-picker/picker. Good for settings screens; less flexible to style:

// npx expo install @react-native-picker/picker
import { Picker } from '@react-native-picker/picker';
import { useState } from 'react';

function NativePicker() {
  const [value, setValue] = useState('apple');
  return (
    <Picker selectedValue={value} onValueChange={setValue}>
      <Picker.Item label="Apple" value="apple" />
      <Picker.Item label="Banana" value="banana" />
      <Picker.Item label="Cherry" value="cherry" />
    </Picker>
  );
}

Props

The props that matter for a custom Modal dropdown:

PropTypeDefaultDescription
optionsstring[]The list of selectable values.
valuestring | nullnullCurrently selected value (controlled).
onChangefnCalled with the picked value.
placeholderstring'Select…'Shown on the trigger when nothing is selected.
transparentbooleantrueModal prop — required so the backdrop shows through.
onRequestClosefnModal prop — fires on Android back button. Always set it.

Common patterns

Objects, not strings: when options are { label, value }, render item.label and call onChange(item.value); set keyExtractor to item.value.

Multi-select: keep a Setof selected values, toggle on tap, and don’t close the Modal until the user confirms.

Gotchas

  • Don’t build the menu with position: 'absolute' — it gets clipped by parent overflow and scroll views. A Modal always floats on top.
  • Always set onRequestCloseon the Modal or the Android hardware back button won’t dismiss the dropdown.
  • In a searchable dropdown, set keyboardShouldPersistTaps="handled" on the FlatList or the first tap only dismisses the keyboard instead of selecting an item.
  • Give the backdrop Pressable an onPressthat closes the Modal, but stop propagation on the menu itself so taps inside don’t close it.
  • Duplicate keys crash the list. Make sure each option is unique, or derive a unique keyExtractor.

FAQ

Does React Native have a dropdown component? No. Build one from a Modal + FlatList, or install @react-native-picker/picker.

Modal dropdown or a library?Start with the dependency-free Modal — it’s ~30 lines, works cross-platform, and adds nothing to your bundle. Reach for a library only if you need advanced features like grouped sections or async loading.

How do I make it searchable? Add a TextInput above the list and filter a memoized copy of the options (see the searchable example).

Related components

Skip the boilerplate

Describe your screen in ShipNative and it wires up the component for you — in a real, exportable React Native app.

Generate it with AI →