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.


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 gallery. 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 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 launchImageLibraryAsync() method to display the system UI by choosing an image or a video from the device's media library. We'll use the primary themed button created in the previous chapter to select an image from the device's media library and create a function to launch the device's image library to implement this functionality.

In src/app/(tabs)/index.tsx, import 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 () => { let 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() 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.

3

Update the button component

On pressing the primary button, we'll call the pickImageAsync() function on the Button component. Update the onPress prop of the Button component in src/components/button.tsx:

src/components/button.tsx
import { StyleSheet, View, Pressable, Text } from 'react-native'; import FontAwesome from '@expo/vector-icons/FontAwesome'; type Props = { label: string; theme?: 'primary'; onPress?: () => void; }; export default function Button({ label, theme, onPress }: Props) { if (theme === 'primary') { return ( <View style={[ styles.buttonContainer, { borderWidth: 4, borderColor: '#ffd33d', borderRadius: 18 }, ]}> <Pressable style={[styles.button, { backgroundColor: '#fff' }]} onPress={onPress}> <FontAwesome name="picture-o" size={18} color="#25292e" style={styles.buttonIcon} /> <Text style={[styles.buttonLabel, { color: '#25292e' }]}>{label}</Text> </Pressable> </View> ); } return ( <View style={styles.buttonContainer}> <Pressable style={styles.button} onPress={() => alert('You pressed a button.')}> <Text style={styles.buttonLabel}>{label}</Text> </Pressable> </View> ); } const styles = StyleSheet.create({ buttonContainer: { width: 320, height: 68, marginHorizontal: 20, alignItems: 'center', justifyContent: 'center', padding: 3, }, button: { borderRadius: 10, width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', flexDirection: 'row', }, buttonIcon: { paddingRight: 8, }, buttonLabel: { color: '#fff', fontSize: 16, }, });

In src/app/(tabs)/index.tsx, add the pickImageAsync() function to the onPress prop on the first <Button>.

src/app/(tabs)/index.tsx
import { View, StyleSheet } from 'react-native'; 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 () => { let 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 ( <View 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" /> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#25292e', alignItems: 'center', }, imageContainer: { flex: 1, }, 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: