This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

Use an image picker

Edit page

In this tutorial, learn how to use Expo Image Picker to select an image from the media library and show it in a React Native app on Android, iOS, and web.


React Native provides built-in components as standard building blocks, such as <View>, <Text>, and <Pressable>. We are building a feature to select an image from the device's media library. This isn't possible with the core components and we'll need a library to add this feature in our app.

We'll use expo-image-picker, a library from the Expo SDK.

Watch: Using an image picker in your universal Expo app
Watch: Using an image picker in your universal Expo app

Learn how to use expo-image-picker to select images from the device's media library.


1

Install expo-image-picker

To install the expo-image-picker library, stop the development server by pressing Ctrl + C in the terminal, then run the following command:

Terminal
- npx expo install expo-image-picker
- yarn expo install expo-image-picker
- pnpm expo install expo-image-picker
- bun expo install expo-image-picker

The npx expo install command will install the library and add it to the project's dependencies in package.json.

2

Pick an image from the device's media library

expo-image-picker provides the launchImageLibraryAsync() method, which opens the system UI to select an image or a video from the device's media library. We'll create a function that calls this method, and then connect it to the primary button from the previous chapter.

In src/app/(tabs)/index.tsx, import the expo-image-picker library and create a pickImageAsync() function inside the Index component:

src/app/(tabs)/index.tsx
// ...rest of the import statements remain unchanged import * as ImagePicker from 'expo-image-picker'; export default function Index() { const pickImageAsync = async () => { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], allowsEditing: true, quality: 1, }); if (!result.canceled) { console.log(result); } else { alert('You did not select any image.'); } }; // ...rest of the code remains same }

Let's learn what the above code does:

  • The launchImageLibraryAsync() method receives an object to specify different options. This object is the ImagePickerOptions object, which we are passing when invoking the method.
  • When allowsEditing is set to true, the user can crop the image during the selection process on Android and iOS. On web, the browser's file picker opens without a crop step.

3

Connect the button to the image picker

The Button component from the previous chapter already accepts an onPress prop. In src/app/(tabs)/index.tsx, pass the pickImageAsync() function to the onPress prop of the first <Button>:

src/app/(tabs)/index.tsx
import { Platform, View, StyleSheet } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import * as ImagePicker from 'expo-image-picker'; import Button from '@/components/button'; import ImageViewer from '@/components/image-viewer'; const PlaceholderImage = require('@/assets/images/background-image.png'); export default function Index() { const pickImageAsync = async () => { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], allowsEditing: true, quality: 1, }); if (!result.canceled) { console.log(result); } else { alert('You did not select any image.'); } }; return ( <SafeAreaView style={styles.container}> <View style={styles.imageContainer}> <ImageViewer imgSource={PlaceholderImage} /> </View> <View style={styles.footerContainer}> <Button theme="primary" label="Choose a photo" onPress={pickImageAsync} /> <Button label="Use this photo" onPress={() => alert('You pressed a button.')} /> </View> </SafeAreaView> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#25292e', alignItems: 'center', }, imageContainer: { flex: 1, paddingTop: Platform.select({ web: 96, default: 20 }), }, footerContainer: { flex: 1 / 3, alignItems: 'center', }, });

The pickImageAsync() function invokes ImagePicker.launchImageLibraryAsync() and then handles the result. The launchImageLibraryAsync() method returns an object containing information about the selected image.

Here is an example of the result object and the properties it contains:

{ "assets": [ { "assetId": null, "base64": null, "duration": null, "exif": null, "fileName": "ea574eaa-f332-44a7-85b7-99704c22b402.jpeg", "fileSize": 4513577, "height": 4570, "mimeType": "image/jpeg", "rotation": null, "type": "image", "uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252FStickerSmash-13f21121-fc9d-4ec6-bf89-bf7d6165eb69/ImagePicker/ea574eaa-f332-44a7-85b7-99704c22b402.jpeg", "width": 2854 } ], "canceled": false }

4

Use the selected image

The result object provides the assets array, which contains the uri of the selected image. Let's take this value from the image picker and use it to show the selected image in the app.

Modify the src/app/(tabs)/index.tsx file:

  1. Declare a state variable called selectedImage using the useState hook from React. We'll use this state variable to hold the URI of the selected image.
  2. Update the pickImageAsync() function to save the image URI in the selectedImage state variable.
  3. Pass the selectedImage as a prop to the ImageViewer component.
src/app/(tabs)/index.tsx
import { useState } from 'react'; import { Platform, View, StyleSheet } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import * as ImagePicker from 'expo-image-picker'; import Button from '@/components/button'; import ImageViewer from '@/components/image-viewer'; const PlaceholderImage = require('@/assets/images/background-image.png'); export default function Index() { const [selectedImage, setSelectedImage] = useState<string | undefined>(undefined); const pickImageAsync = async () => { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], allowsEditing: true, quality: 1, }); if (!result.canceled) { setSelectedImage(result.assets[0].uri); } else { alert('You did not select any image.'); } }; return ( <SafeAreaView style={styles.container}> <View style={styles.imageContainer}> <ImageViewer imgSource={PlaceholderImage} selectedImage={selectedImage} /> </View> <View style={styles.footerContainer}> <Button theme="primary" label="Choose a photo" onPress={pickImageAsync} /> <Button label="Use this photo" onPress={() => alert('You pressed a button.')} /> </View> </SafeAreaView> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#25292e', alignItems: 'center', }, imageContainer: { flex: 1, paddingTop: Platform.select({ web: 96, default: 20 }), }, footerContainer: { flex: 1 / 3, alignItems: 'center', }, });

Pass the selectedImage prop to the ImageViewer component to display the selected image instead of a placeholder image.

  1. Modify the src/components/image-viewer.tsx file to accept the selectedImage prop.
  2. The source of the image is getting long, so let's also move it to a separate variable called imageSource.
  3. Pass imageSource as the value of the source prop on the Image component.
src/components/image-viewer.tsx
import { StyleSheet } from 'react-native'; import { Image, type ImageSource } from 'expo-image'; type Props = { imgSource: ImageSource; selectedImage?: string; }; export default function ImageViewer({ imgSource, selectedImage }: Props) { const imageSource = selectedImage ? { uri: selectedImage } : imgSource; return <Image source={imageSource} style={styles.image} />; } const styles = StyleSheet.create({ image: { width: 320, height: 440, borderRadius: 18, }, });

In the above snippet, the Image component uses a conditional operator to load the image's source. The picked image is a uri string, not a local asset like the placeholder image.

Let's take a look at our app now:

Summary

Chapter 4: Use an image picker

We've successfully added the functionality to pick an image from the device's media library.

In the next chapter, we'll learn how to create an emoji picker modal component.

Next: Chapter 5: Create a modal