An in-depth guide on how to use React Native Image Picker

Published on Apr 27, 2020

16 min read

REACT-NATIVE

React Native as a framework to develop cross-platform mobile apps has few options to select an image from a user's mobile phone gallery or camera and perform further actions on it. One module that does that is called react-native-image-picker.

This module is maintained by React Native community and is also one of the reasons I highly recommend this module for you to use. It uses native UI to select a photo or a video from the mobile phone's library or the camera of that device.

In this tutorial, let us start from basics on how to integrate this module for both iOS and Android platforms in a React Native app. Then proceed further to use this module by having a look at some of the common ways to solve different problems when developing an app.

What you need to follow this tutorial?

🔗

To follow this tutorial, ensure your dev environment includes the following required packages:

  • Node.js above 10.x.x installed on your local machine
  • watchman the file watcher, installed
  • react-native-cli installed through npm or access via npm/yarn or npx
  • cocoapods for iOS only
  • Do note that the following tutorial is going to use the react-native version 0.62.x. Please make sure you’re using a version of React Native above 0.60.x.

For a complete walk-through on setting up a development environment for React Native, you can go through the official documentation here.

Create a new react native app

🔗

Start by creating a new React Native app. Open a terminal window and execute the following command. I am going to use npx to access the latest React Native CLI version. After the project directory is created, please make sure that you navigate inside the directory.

npx react-native init rnImagePickerExample
# navigate to project directory
cd rnImagePickerExample
# after navigating inside the directory
# install pods for iOS development
npx pod-install

Thanks to awesome open-source developers at Expo pod-install is an awesome package that lets you install Cocapods essential to build and run react-native apps for iOS. You don't have to dwell inside the ios/ directory and navigate back to the root project. It takes care of that extra step.

Build the app for the specific mobile OS you are building the app for by running either of the two commands as below:

# for iOS
npx react-native run-ios
# for android
npx react-native run-android

Go to the simulator or the device you have connected to run this app and you are going to get default React Native app.

Cheers! You have created a new React Native app. Let us now get started with this tutorial.

Install and configure react-native-image-picker

🔗

Start by running the below command from a terminal window to install the image picker module.

yarn add react-native-image-picker

Once you have done this step, you are going to get a success message in your terminal window as shown below. After installing pods, you have to make sure to add permissions. If you do not add this step, the app might crash or won't work when using react-native-image-picker.

iOS permissions

🔗

For iOS, open /ios/rnImagePickerExample/Info.plist file and the following:

1<plist version="1.0">
2 <dict>
3 // ...
4 // add the following
5 <key>NSPhotoLibraryUsageDescription</key>
6 <string>$(PRODUCT_NAME) would like access to your photo gallery</string>
7 <key>NSCameraUsageDescription</key>
8 <string>$(PRODUCT_NAME) would like to use your camera</string>
9 <key>NSPhotoLibraryAddUsageDescription</key>
10 <string>$(PRODUCT_NAME) would like to save photos to your photo gallery</string>
11 <key>NSMicrophoneUsageDescription</key>
12 <string>$(PRODUCT_NAME) would like to use your microphone (for videos)</string>
13 </dict>
14</plist>

There is an essential step to make sure you ask for the right permission with the right message, especially if you are looking forward to publishing your app on the store.

CocoaPods installation

🔗

Another necessary step to make this app run on iOS is to install Cocoapods for the image picker library we have just installed. After the release of React Native 0.60, the team behind the framework introduced auto-linking so we do not require to link the library. This is "auto-linking" is done by installing pods.

npx pod-install

Make sure to run the build command mentioned in the previous section to run the app again after this step.

Android permissions

🔗

Similarly, for Android, you have to add the required permissions in the file /android/app/src/main/AndroidManifest.xml. The first permission is to access the device's camera and the second permission is to read or write to storage. This second option for the current demo app means to allow us to choose the image from the device's image gallery.

1<uses-permission android:name="android.permission.CAMERA" />
2<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

That's it to install and configure an image picker library in a react native app. For more information check out official doc here.

Create a simple image picker screen component

🔗

The advantage of the React Native Image Picker library is the number of options it provides in the options it provides for you set and use in your app. The simplest options like changing the title of the picker button, or the cancel button, setting the max height and width of the image picked, there are some advance options such as skipBack and so on that are useful when uploading or communicating with a backend service.

Start by creating a simple image picker screen component. Make sure you are at the root location of your project to follow these steps.

  • Create a new directory called src.
  • Inside src create a new sub-directory to store all screen components called screens. This is a common convention to keep all screen components inside a React Native app.
  • Inside the sub-directory create the screen component file called SimpleImagePicker.js as well as a global a style file called Styles.js.

Inside the Styles.js let us define some basic styles using StyleSheet object from React Native core API. In the snippet below, you are also going to find some hex color codes that are going to be used throughout this tutorial. Feel free to change these values as per your preference.

1// Global shared styles for screens
2
3import { StyleSheet } from 'react-native';
4
5export const STYLES = StyleSheet.create({
6 flex: {
7 flex: 1
8 },
9 centerContainer: {
10 alignItems: 'center',
11 justifyContent: 'center'
12 },
13 title: {
14 fontSize: 22
15 }
16});
17
18export const COLORS = {
19 primaryDark: '#22212c',
20 primaryLight: '#f8f8f2',
21 primaryRed: '#ff5555',
22 primaryPink: '#ff80bf',
23 primaryYellow: '#ffff80',
24 primaryOrange: '#ff9580'
25};

Typically you define these types of styles, as mentioned in the above code snippet, for a particular screen. But if you are planning to have more than one screen component, you can share styles by creating a global file.

Next, inside SimpleImagePicker.js file, start by importing necessary statements as well as styles that you have just created.

Then create a basic component that displays a <Text> inside the functional component SimpleImagePicker().

1import React, { useState } from 'react';
2import { View, Text } from 'react-native';
3import { STYLES, COLORS } from './Styles';
4
5export default function SimpleImagePicker() {
6 const [imageSource, setImageSource] = useState(null);
7 return (
8 <View
9 style={[
10 STYLES.flex,
11 STYLES.centerContainer,
12 { backgroundColor: COLORS.primaryDark }
13 ]}
14 >
15 <Text style={[STYLES.title, { color: COLORS.primaryLight }]}>
16 Simple Image Picker
17 </Text>
18 </View>
19 );
20}

The state variable imageSource in the above snippet is going to store the value of the URI or the source of the image on the device when a user chooses an image.

To see this screen component in action, one last step left is to modify the App.js file as shown below.

1import React from 'react';
2import { StatusBar } from 'react-native';
3import SimpleImagePicker from './src/screens/SimpleImagePicker';
4
5export default function () {
6 return (
7 <>
8 <StatusBar barStyle="light-content" />
9 <SimpleImagePicker />
10 </>
11 );
12}

Go back to a simulator or the physical device you are using to run this app and you are going to be welcomed by the following screen.

How to pick an image?

🔗

In this section let us get create a handler method that is going to allow the user to pick an image. To start make sure you update the import statements by importing core components from React Native such as TouchableOpacity and Alert. Also, import ImagePicker from react-native-image-picker library.

Then inside, the screen component creates a new handler method called selectImage(). This method is going to trigger a button on the screen when the user wants to select an image from the device's library from <TouchableOpacity>.

Inside this method, you are going to an options object with some primary options like the title of the image picker, the maximum width, and height of an image, and setting storage options to not backup an image selected. This options object is used for customization and its not mandatory. This object is also passed as the first argument to the method that actually selects an image.

ImagePicker library has a method called showImagePicker which accepts an object called response as the second argument. This method's only job is to display the image picker. It shows an alert box when the button is pressed to select an image.

The response object is the most important. It has properties to determine like when the user cancels the process of picking an image from the library or there is an error in the process of picking an image, the URI of the local file asset select by the user, and so on.

We are going to use some of the basic options like did cancel, error, customButton, and uri.

Modify the screen component file as shown below.

1import React, { useState } from 'react';
2import { View, Text, TouchableOpacity, Alert } from 'react-native';
3import { STYLES, COLORS } from './Styles';
4import ImagePicker from 'react-native-image-picker';
5
6export default function SimpleImagePicker() {
7 const [imageSource, setImageSource] = useState(null);
8
9 function selectImage() {
10 let options = {
11 title: 'You can choose one image',
12 maxWidth: 256,
13 maxHeight: 256,
14 storageOptions: {
15 skipBackup: true
16 }
17 };
18
19 ImagePicker.showImagePicker(options, response => {
20 console.log({ response });
21
22 if (response.didCancel) {
23 console.log('User cancelled photo picker');
24 Alert.alert('You did not select any image');
25 } else if (response.error) {
26 console.log('ImagePicker Error: ', response.error);
27 } else if (response.customButton) {
28 console.log('User tapped custom button: ', response.customButton);
29 } else {
30 let source = { uri: response.uri };
31 console.log({ source });
32 }
33 });
34 }
35
36 return (
37 <View
38 style={[
39 STYLES.flex,
40 STYLES.centerContainer,
41 { backgroundColor: COLORS.primaryDark }
42 ]}
43 >
44 <Text style={[STYLES.title, { color: COLORS.primaryLight }]}>
45 Simple Image Picker
46 </Text>
47 <TouchableOpacity
48 onPress={selectImage}
49 style={[
50 STYLES.selectButtonContainer,
51 { backgroundColor: COLORS.primaryLight }
52 ]}
53 >
54 <Text style={STYLES.selectButtonTitle}>Pick an image</Text>
55 </TouchableOpacity>
56 </View>
57 );
58}

Also, modify the Styles.js file and add the styles for the new button you have just created.

1export const STYLES = StyleSheet.create({
2 flex: {
3 flex: 1
4 },
5 centerContainer: {
6 alignItems: 'center',
7 justifyContent: 'center'
8 },
9 title: {
10 fontSize: 22
11 },
12 // add below
13 selectButtonContainer: {
14 margin: 20,
15 borderRadius: 5
16 },
17 selectButtonTitle: {
18 padding: 10,
19 fontSize: 18
20 }
21});

Now go back to the simulator and you are going to see the new button we have just added is being displayed.

Click the button and there is going to be an alert box pop up.

It gives you the option to select an image from the library or take a photo from the device's camera (Since I am using a simulator, taking a photo is not possible).

At this moment, if you press Cancel, you are going to see another alert box (that we intentionally added to the screen component).

The console statements are also being logged correctly by the metro bundler terminal window. You can verify that as shown in the image below.

To make the alert box disappear, click the button Ok. Click the UI button to select an image again, and this time, choose an image from the library.

The first thing it is going to do is to ask for permission. This only happens for the first time when the user is using the app.

Next, select an image if you have in the library as shown below.

After you have selected the image, nothing happens. This is because we still have to write the code to display the image. For now, go to the terminal window and you are going to the response object as well source object with data and information about the image.

If it is not visible or understandable, take a look at the JSON snippet below.

1{
2 "response": {
3 "data": "/9j/4AAQSkZJRgABAQAAAQABAAD/
4 4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAIQAABtbnRyUkdC
5 IFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAA
6 AAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAA
7 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
8 AAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAAB
9 eAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAAB
10 oAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB
11 3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMA
12 UgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
13 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
14 AAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFla
15 IAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA
16 +EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAA
17 pbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAA
18 AAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIA
19 BJAG4AYwAuACAAMgAwADEANv/
20 bAEMAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE
21 BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/
22 bAEMBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE
23 BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/
24 AABEIAQABAAMBIgACEQEDEQH/
25 xAAVAAEBAAAAAAAAAAAAAAAAAAAAC//
26 EABQQAQAAAAAAAAAAAAAAAAAAAAD/
27 xAAUAQEAAAAAAAAAAAAAAAAAAAAA/
28 8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/
29 aAAwDAQACEQMRAD8An/
30 gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
31 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
32 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
33 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
34 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
35 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
36 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
37 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
38 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
39 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
40 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//2Q==",
41 "fileName": "image-4be54ecf-83c7-4819-bf37-b549cd3efa71.jpg",
42 "fileSize": 1222,
43 "height": 256,
44 "isVertical": true,
45 "originalRotation": 0,
46 "path": "/storage/emulated/0/Pictures/image-4be54ecf-83c7-4819-bf37-b549cd3efa71.jpg",
47 "type": "image/jpeg",
48 "uri": "file:///storage/emulated/0/Pictures/
49 image-4be54ecf-83c7-4819-bf37-b549cd3efa71.jpg",
50 "width": 256
51 }
52}

The response object returns details related to the image such as:

  • data: base64 encoded image data generated
  • fileSize: the size of the file
  • fileName: the name of the file name
  • type: media type such as image/jpeg
  • uri: which is also the value of the source object
  • the width and height but with dimensions that we passed as the properties of options object and not the actual image size (which is 500px x 500px).

You can stop the base64 data generation of the image by adding another property called noData: true in options object and it will stop generating the base64 if there is no requirement.

1let options = {
2 // rest of the properties remain same
3 noData: true
4};

After adding this property, the new response object won't have a data field.

The type of the source is essential for the image picker to know such as if you only want the user to select an image instead of a video file, then you can set another property called mediaType at options object.

1let options = {
2 // rest of the properties remain same
3 mediaType: 'photo' // other values 'video', 'mixed'
4};

By setting the value to mixed for this property type will allow the user to select either an image or a video. There are other options on how you can control the user's input when selecting an image or a video that you can find in the official documentation here of the image picker library.

Difference between launchImageLibrary() and showImagePicker()?

🔗

There are separate functions provided by ImagePicker to use for selected methods:

  • launchCamera(options?, (response) => {})
  • launchImageLibrary(options?, (response) => {})

Using these methods eliminates the need of showing the alert box to select an option when choosing an image.

These methods are for a direct use case such as when you only want the user to select the image either from the device's library or take a photo from the device's camera. You want to give the user only one option from these two, then you should use one of these methods.

The working of either of these methods is similar to showImagePicker. Let us try one of them. Replace the method showImagePicker() with launchImageLibrary() in the screen component file.

1ImagePicker.launchImageLibrary(options, response => {
2 console.log({ response });
3
4 if (response.didCancel) {
5 console.log('User cancelled photo picker');
6 Alert.alert('You did not select any image');
7 } else if (response.error) {
8 console.log('ImagePicker Error: ', response.error);
9 } else if (response.customButton) {
10 console.log('User tapped custom button: ', response.customButton);
11 } else {
12 let source = { uri: response.uri };
13 console.log({ source });
14 }
15});

Now go back to the device and you are going to notice only one difference. The image library opens as soon as the button from the app is clicked.

The rest of the process is going to be the same.

Display the image

🔗

In this section, let us complete the demo app by displaying the image when the user picks an image from the library. We are also going to display a placeholder image when no image is being selected by the user.

To start you are going to import the Image from react native core API. Then update the handler function by setting the source uri of the image to the state variable image source we defined in the earlier section.

Lastly, you update the JSX of the component.

Here is the complete code snippet for the SimpleImagePicker screen component. We are going to conditionally render when to show the placeholder image from a local asset file and when to display the image that the user has picked.

1import React, { useState } from 'react';
2import { View, Text, TouchableOpacity, Alert, Image } from 'react-native';
3import { STYLES, COLORS } from './Styles';
4import ImagePicker from 'react-native-image-picker';
5
6export default function SimpleImagePicker() {
7 const [imageSource, setImageSource] = useState(null);
8
9 function selectImage() {
10 let options = {
11 title: 'You can choose one image',
12 maxWidth: 256,
13 maxHeight: 256,
14 noData: true,
15 mediaType: 'photo',
16 storageOptions: {
17 skipBackup: true
18 }
19 };
20
21 ImagePicker.launchImageLibrary(options, response => {
22 if (response.didCancel) {
23 console.log('User cancelled photo picker');
24 Alert.alert('You did not select any image');
25 } else if (response.error) {
26 console.log('ImagePicker Error: ', response.error);
27 } else if (response.customButton) {
28 console.log('User tapped custom button: ', response.customButton);
29 } else {
30 let source = { uri: response.uri };
31
32 // ADD THIS
33 setImageSource(source.uri);
34 }
35 });
36 }
37
38 return (
39 <View
40 style={[
41 STYLES.flex,
42 STYLES.centerContainer,
43 { backgroundColor: COLORS.primaryDark }
44 ]}
45 >
46 <Text style={[STYLES.title, { color: COLORS.primaryLight }]}>
47 Simple Image Picker
48 </Text>
49 {/* ADD THIS */}
50 <View style={STYLES.imageContainer}>
51 {imageSource === null ? (
52 <Image
53 source={require('../assets/placeholderimage.jpg')}
54 style={STYLES.imageBox}
55 resizeMode="contain"
56 />
57 ) : (
58 <Image
59 source={{ uri: imageSource }}
60 style={STYLES.imageBox}
61 resizeMode="contain"
62 />
63 )}
64 </View>
65 <TouchableOpacity
66 onPress={selectImage}
67 style={[
68 STYLES.selectButtonContainer,
69 { backgroundColor: COLORS.primaryLight }
70 ]}
71 >
72 <Text style={STYLES.selectButtonTitle}>Pick an image</Text>
73 </TouchableOpacity>
74 </View>
75 );
76}

Also, update the Styles.js file:

1export const STYLES = StyleSheet.create({
2 // rest of the styles remain same
3 // ADD BELOW
4 imageContainer: {
5 marginVertical: 20,
6 borderWidth: 5,
7 borderColor: '#ff5555'
8 },
9 imageBox: {
10 width: 256,
11 height: 256
12 }
13});

Go back to the app and when an image is not picked, you are going to see the following result.

When an image is selected, it is going to be displayed instead of the placeholder image.

Conclusion

🔗

In this post, you have learned how to configure and implement react-native-image-picker library to allow a user to pick an image from their device library. When on a physical device, try testing the above code snippet using the device's Camera. The core functionalities discussed in this post are important to customize and advance further to add more functionalities.

Here is the link to the complete API for react-native-image-picker library.

The complete code for this tutorial is available at this GitHub repo here.

Originally Published at Crowdbotics.


More Posts

Browse all posts

Aman Mittal author

I'm a software developer and a technical writer. In this blog, I write about Technical writing, Node.js, React Native and Expo.

Currently, working at Expo. Previously, I've worked as a Developer Advocate, and Senior Content Developer with companies like Draftbit, Vercel and Crowdbotics.


Copyright ©  2019-2022 Aman Mittal · All Rights Reserved.