Waldo sessions now support scripting! – Learn more
App Development

Build a React Native Picker: Tutorial With Examples

Siddhant Varma
Siddhant Varma
Build a React Native Picker: Tutorial With Examples
November 2, 2021
11
min read
React Native picker
React Native picker

When you’re building mobile apps, one of the most common components you need is a picker. A picker allows you to use your system’s UI component to choose an option from a list. From choosing dates for booking flights to selecting options in a form, pickers are used everywhere.

In this tutorial, we’ll build a React Native picker and understand how it works. I’ll also demonstrate how you can use it alongside numerous examples using the library React-Native-Picker. Finally, we’ll also write some tests for our picker. Let’s get rolling!

A Primer on Pickers

You have likely used select menus and drop-downs on websites. A picker is the equivalent of those in a mobile app. It renders a native UI component to choose a value from a list of options.

This means that if you use a picker on an Android device, it will render Android’s UI component for the picker. Similarly, if you’re on an iOS device, you’ll see a native iOS picker on the screen.

Pickers allow you to create an intuitive way for your users to select an option. They have use cases in all kinds of applications: e-commerce, social media, hotel booking apps, etc. They’re also used in various forms. For instance, if you wish to book a flight on an app, you’ll most likely use a date picker to select dates for your journey.

Another example would be an online menu. You could have a picker that displays a list of food items a user can choose from when ordering their food.

Picker example to select food from a menu
Picker example to select food from a menu

Now that you know what pickers are, let’s go ahead and build one.

Create a New Expo Project

For brevity, we’ll use Expo-CLI to create our React Native application. If you’re new to Expo, you can read about how to get started with it.

Let’s create a new Expo project by running the following:

 
 
expo init rn-picker-tutorial

Choose a blank template for the project. Once the setup completes, run npm start to kickstart your Expo app.

Install React-Native-Picker Library

Luckily, there’s an amazing React Native library that gives you an easy way to use pickers. Let’s install it:

 
 
expo install @react-native-picker/picker

It does all the heavy lifting for us and gives us a simple way to interact with the system UI for rendering pickers in our application. After you’ve installed the library, you may need to restart your Expo server again.

We’re done with the installation. Next, let’s start using this library in our project.

Use a Simple Picker

First things first, you need to import the Picker component from the library wherever you wish to use it. We’ll put most of our code inside our App.js file. So let’s import the Picker component inside our project’s App.js:

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

We’ll also need a state to handle the currently selected option from the picker. So let’s also import the useState hook from React.

 
 
import React,{useState} from 'react';

Next, let’s create a simple state pokemon that stores the currently selected Pokémon from the picker.

 
 
const [pokemon,setPokemon] = useState();

We’ll create a simple picker that allows us to select a Pokémon from a list of them.

Render the Picker

Let’s now render the <Picker> component inside our App.js:

 
 
 <View style={styles.container}>
     <Picker
        selectedValue={pokemon}
      >
      </Picker>
 </View>

The <Picker> component takes the selectedValue prop, which indicates the default selected value for the picker. Since we want this to be dynamic, we have used our pokemon state here.  But where’s the list of options this picker needs to render?

Render Picker Items

The <Picker/> component is actually a higher-order component that renders the <Picker.Item/> component to indicate each option in the picker. Let’s do that:

 
 
  <View style={styles.container}>
     <Picker
        style={styles.pickerStyles}
        selectedValue={pokemon}
        onValueChange={handleValueChange}>
        <Picker.Item label="Pikachu" value="pikachu" />
        <Picker.Item label="Charmander" value="charmander" />
        <Picker.Item label="Squirtle" value="Squirtle" />
      </Picker>
 </View>

Each <Picker.Item/> child component takes in a label and a value prop. The former indicates the name of the option and the latter indicates the value of that option.

Alternately, you can also render these picker items dynamically from an array.

 
 
 import React,{useState} from 'react';
import { StyleSheet, View } from 'react-native';
import {Picker} from '@react-native-picker/picker';
const pokemons=['Pikachu','Charmander','Squirtle'];
export default function App() {
  const [pokemon,setPokemon] = useState();
  return (
    <View style={styles.container}>
     <Picker
        selectedValue={pokemon}
        onValueChange={handleValueChange}>
          {
            pokemons.map(pokemon=> <Picker.Item key={pokemon} label={pokemon} value={pokemon}/>)
          }
      </Picker>
    </View>
  );
}
});

In the above code we cycle through each of the Pokémon present in the pokemons array and render a <Picker.Item/> component for each.

Notice that in the above code we have also added another prop onValueChange to our <Picker/> component.

Set Selected Value Dynamically

Notice that in the above code we have also added another prop onValueChange to our <Picker/> component. This prop takes in a function that is fired whenever an option is selected from the picker. We have assigned it to be the handleValueChange function. However, that function doesn’t exist now.

So let’s go ahead and create it:

 
 
  const handleValueChange=(itemValue, itemIndex) =>setPokemon(itemValue)

Inside the handleValueChange function, we get the itemValue, which indicates the selected value of the picker option. We also get the itemIndex, based on the sequence of rendered picker items. Inside the above handleValueChange function, we simply set the itemValue to our pokemon state using the setPokemon function.

Style the Picker

If you check your app now, you’ll only see a small drop-down arrow on the screen. This is because, by default, you need to set some width to your picker. Let’s use this opportunity to also style the picker.

We can style the <Picker/> component like any other React Native component. First, we need to create a styles object inside our style sheet. Let’s use the default style sheet created inside the App.js for this:

 
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  pickerStyles:{
    width:'70%',
    backgroundColor:'gray',
    color:'white'
  }
});

Now we simply need to assign styles.pickerStyles to the style prop of our <Picker/> component:

 
 
    <View style={styles.container}>
     <Picker
        style={styles.pickerStyles}
        selectedValue={pokemon}
        onValueChange={handleValueChange}>
        <Picker.Item label="Pikachu" value="pikachu" />
        <Picker.Item label="Charmander" value="charmander" />
        <Picker.Item label="Squirtle" value="Squirtle" />
      </Picker>
    </View>

Now you should see a gray picker rendered on the screen as shown:

Picker component UI
Picker component UI

Awesome! If you open this picker, you should also be able to see the list of options. Consequently, you should be able to choose other options from the list as well.

Rendering picker options
Rendering picker options

Great! You’ve learned how to build a picker in your React Native application. Let’s explore some other features of this library and how they can be useful.

Useful Picker Component Props

We have already seen the important props for the <Picker/> component. Next, let’s see some other props that can be useful.

Disable Picker

You may run into use cases where you might want to disable the picker. For instance, you could want to conditionally allow the user to select an item from the picker. Or you might only want premium members of your app to select options.

For this purpose, you can use the enabled prop. You can set the enabled prop inside the <Picker/> component to false. This will disable the <Picker/> completely. You’ll no longer be able to open the list of options, select an item, or do any other kind of interaction with the <Picker/>.

 
 
<Picker
        enabled={false}
       ...
 </Picker>

Render Picker as a Drop-Down

The mode prop allows you to specify the UI component used to render the picker items. By default, the mode is set to a dialog. This is why, when you open the picker, you see a background overlay on the screen.

However, you can change this to render your picker items as a drop-down as well. All you need to do is set the mode prop to dropdown as shown:

 
 
 <Picker
        mode={'dropdown'}
        ...
 </Picker>

If you check the picker now, you should see a drop-down menu instead as shown:

Drop-down mode in picker
Drop-down mode in picker

Change Drop-Down Icon Color

You can also use the dropdownIconColor prop to change the color of the drop-down arrow icon.

 
 
<Picker
        dropdownIconColor={'red'}
        ...
</Picker>

You should now see a red downward arrow as shown in the picker:

 Changing drop-down icon color of picker
Changing drop-down icon color of picker

Focus and Blur Events

You may also wish to programmatically do something when the picker is in a focus or blur state. The focus state represents the state of picker when you’ve clicked it to toggle the list of options.

When you press anywhere outside, the picker is in a blur state. We get access to these states and events of the <Picker/> component. Let’s create a simple state that represents the focus state of the picker:

 
 
 const [isPickerFocused,setIsPickerFocused]=useState()

Next, create a function that toggles this state:

 
 
 const handleFocus=(focus)=>setIsPickerFocused(focus);

To see this in action, let’s render this state inside our App.js right above the <Picker/> component:

 
 
  <Text style={{marginBottom:200}}>Picker is {isPickerFocused ? 'focused' : 'not focused'} </Text>

Now we can call the handleFocus function using the onBlur and onFocus prop that we get access to in our <Picker/> component.

 
  <Picker
        onBlur={()=>handleFocus(false)}
        onFocus={()=>handleFocus(true)}
       ...
 </Picker>

If you now open the Picker, you should see that it’s in a focus state:

Picker in focused state
Picker in focused state

Consequently, if you now close the picker, you should see it in a blur state:

Picker’s blur state

Test Your Picker

What good is your code if it can’t pass all test cases? Automation testing allows you to build robust and foolproof apps. So let’s go ahead and write a simple snapshot test for our picker.

First, we need to install a few libraries for this purpose:

 
 
npm i jest jest-expo @testing-library/react-native

At the root of our project, create an App.test.js file with the following code:

 
 
import React from 'react';
import {render} from '@testing-library/react-native'
import App from './App';
describe('<App />', () => {
  it('should match snapshot', () => {
    const app=render(<App />);
    const picker = app.getByTestId('test-picker')
    expect(picker).toMatchSnapshot()
  });
});

In the above code, we first grab our app component using the render function. Then, we get the <Picker/> component using a testID prop. Finally, we call the toMatchSnapshot() method, which compares snapshots of our <Picker/> component rendered in our app.

However, we need to assign a testID prop to our <Picker/> component. Only then will we be able to get a reference to our <Picker/> component. Head back to your App.js and add the testID prop to the <Picker/> component as shown:

 
 
  <Picker
        testID={'test-picker'}
        ...
  />

Great! You’re good to go now. Let’s run our snapshot test by running the following:

 
 
npm run test

And voilà! We see that our <Picker/> component has passed the snapshot test with flying colors!

Snapshot test result
Snapshot test result

But there’s a lot more you can do than snapshot testing. You could write more unit or end-to-end tests to make your picker component more foolproof. However, testing sometimes becomes a different ball game altogether, and most developers struggle to write great tests that make their apps stable.

In these situations, no-code testing tools are a lifesaver. For this, check out Waldo, which allows you to easily write and record automated tests in your browser without writing a single line of code!

Now that you've learned how to create and use pickers in your React Native application, a great exercise would be to use that knowledge to build something awesome!

Wrapping Up

Now that you’ve learned how to create and use pickers in your React Native application, a great exercise would be to use that knowledge to build something awesome! For instance, you can build a form in your app that allows users to choose an option via a picker. Or you could style these pickers in a way that fits the design system of your app. We explored a bunch of cool props that the library offers, but there’s more to it that might be useful for you.

Automated E2E tests for your mobile app

Waldo provides the best-in-class runtime for all your mobile testing needs.
Get true E2E testing in minutes, not months.

Reproduce, capture, and share bugs fast!

Waldo Sessions helps mobile teams reproduce bugs, while compiling detailed bug reports in real time.