React Native Dropdown: With and Without a Library

React Native ships no dropdown or select in its core component list. You either build one from a Pressable trigger, a Modal and a FlatList of options, or install the community package @react-native-picker/picker, which wraps the native picker on Android and iOS. Build your own when you need search, custom rows or one look on every platform.

Three ways to show a list of choices
ApproachInstallBest for
Pressable + Modal + FlatListNothing, all coreCustom styling, search, long lists
@react-native-picker/pickernpm install @react-native-picker/pickerThe platform's own picker look
ActionSheetIOSNothing, iOS onlyA short list of actions on iPhone

Updated

The preview below runs the same logic as the React Native code further down, drawn with web elements so you can try it here: open the list, filter it, pick a row and close it with Escape. Then copy the component and swap the web tags for View, Text, Pressable, Modal and FlatList.

Dropdown preview

Web stand-in for the React Native component: the same open, filter and pick logic, drawn with HTML so it runs here.

Nothing selected yet.

Props that matter for a dropdown

Core props used by the custom dropdown
ComponentPropWhat it does
ModalvisibleShows or hides the list (default true)
ModaltransparentRenders over a see-through background instead of filling the screen
ModalanimationType"none" (default), "slide" or "fade"
ModalonRequestCloseCalled for the Android back button; required on Android
FlatListdata / renderItemThe options array and the function that draws each row
FlatListkeyExtractorReturns a unique key per option
FlatListkeyboardShouldPersistTaps"never" (default), "always" or "handled"
PickermodeAndroid only: "dialog" (default) or "dropdown"

Copyable dropdown code

Dropdown from Pressable, Modal and FlatList

No dependencies. The parent owns the value; the component only reports the choice through onChange.

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

export function Dropdown({ label, options, value, onChange }) {
  const [open, setOpen] = useState(false);
  return (
    <View>
      <Pressable
        accessibilityRole="button"
        accessibilityLabel={`${label}: ${value ?? "none"}`}
        onPress={() => setOpen(true)}
        style={s.trigger}
      >
        <Text>{value ?? "Choose..."}</Text>
      </Pressable>
      <Modal visible={open} transparent animationType="fade" onRequestClose={() => setOpen(false)}>
        <Pressable style={s.backdrop} onPress={() => setOpen(false)}>
          <View style={s.sheet}>
            <FlatList
              data={options}
              keyExtractor={(item) => item}
              keyboardShouldPersistTaps="handled"
              renderItem={({ item }) => (
                <Pressable
                  accessibilityRole="button"
                  accessibilityState={{ selected: item === value }}
                  onPress={() => { onChange(item); setOpen(false); }}
                  style={({ pressed }) => [s.row, pressed && s.pressed]}
                >
                  <Text style={item === value ? s.bold : null}>{item}</Text>
                </Pressable>
              )}
            />
          </View>
        </Pressable>
      </Modal>
    </View>
  );
}

const s = StyleSheet.create({
  trigger: { borderWidth: 1, borderColor: "#cbd5e1", borderRadius: 8, padding: 12 },
  backdrop: { flex: 1, backgroundColor: "rgba(0,0,0,0.4)", justifyContent: "center", padding: 24 },
  sheet: { backgroundColor: "#fff", borderRadius: 12, maxHeight: "70%" },
  row: { padding: 14 },
  pressed: { backgroundColor: "#f1f5f9" },
  bold: { fontWeight: "700" },
});

The community Picker

Install with npm install @react-native-picker/picker. onValueChange receives the item value and its position.

import { useState } from "react";
import { Picker } from "@react-native-picker/picker";

export function CityPicker() {
  const [city, setCity] = useState("toronto");
  return (
    <Picker
      selectedValue={city}
      onValueChange={(value, index) => setCity(value)}
      mode="dropdown" // Android only
    >
      <Picker.Item label="Toronto" value="toronto" />
      <Picker.Item label="Vancouver" value="vancouver" />
      <Picker.Item label="Montreal" value="montreal" />
    </Picker>
  );
}

When to build your own

The community Picker is the quickest route and looks native on each platform, which also means it looks different on Android and iOS. If your design calls for the same list everywhere, a filter box, icons, or two lines per row, the Modal version gives you full control in about fifty lines.

FlatList only renders the rows near the screen, so a list of countries or time zones stays fast inside the Modal. A plain map over a long array inside a ScrollView renders everything at once.

Accessibility for a custom select

Screen readers cannot guess that your Pressable opens a list. Give it accessibilityRole="button", a label that names the field and its current value, and set accessibilityState with selected: true on the chosen row inside the list.

Closing the list should return the user to the trigger. Keep the Modal's onRequestClose wired up and add a visible close control for people who do not use the back gesture.

How it works

  1. A Pressable shows the current choice, or a placeholder when nothing is picked.
  2. Pressing it sets an open flag, which makes a Modal visible.
  3. Inside the Modal, a FlatList renders one Pressable row per option.
  4. Tapping a row calls onChange with the value and sets the flag back to false.
  5. onRequestClose handles the Android back button so the list can always be dismissed.

Tips

Frequently asked questions

Does React Native have a built-in dropdown?

No. The core components page lists Button and Switch under user interface controls, and nothing for selects. For a ready-made native select, install the community package @react-native-picker/picker.

How do I make the Picker look like a dropdown on Android?

Set mode="dropdown" on the Picker. That prop is Android only; the default there is "dialog", which opens a modal list. On iOS the component shows the native wheel instead.

Why does tapping an option only close the keyboard?

A scrolling list defaults keyboardShouldPersistTaps to "never", so the first tap outside the focused input dismisses the keyboard and the row never receives it. Set the prop to "handled" on the FlatList.

Can I add search to a React Native dropdown?

Yes, with the custom build. Keep a query string in state, put a TextInput at the top of the Modal, and pass the filtered array to the FlatList data prop.

Related: React vs React Native, React Native forms, React Native radio buttons, React Native TextInput props, React hooks cheat sheet.

Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.

More in Guides

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap