xref: /expo/docs/pages/tutorial/image-picker.mdx (revision bfbbd417)
1---
2title: Picking an image
3---
4
5import { SnackInline } from '~/ui/components/Snippet';
6import Video from '~/components/plugins/Video';
7import { Terminal } from '~/ui/components/Snippet';
8
9So far we have been using code from React and React Native in our app. React gives us a nice way to build components and React Native gives us pre-built components that work on iOS, Android, and web — like `View`, `Text`, `TouchableOpacity`. React Native does _not_ provide us with an image picker. For this, we can use an Expo library called [expo-image-picker](/versions/latest/sdk/imagepicker):
10
11> `expo-image-picker` provides access to the system's UI for selecting images and videos from the phone's library or taking a photo with the camera.
12
13## Installing expo-image-picker
14
15To use `expo-image-picker` in our project, we first need to install it. In your project directory, run the following command:
16
17<Terminal cmd={['$ npx expo install expo-image-picker']} />
18
19This will tell npm (or yarn) to install a version of the `expo-image-picker` library that is compatible with your project.
20
21## Picking an image
22
23With the library installed in our project, we can now actually use it.
24
25<SnackInline label="Image picker" templateId="tutorial/image-picker-log" dependencies={['expo-image-picker']}>
26
27{/* prettier-ignore */}
28```js
29import React from 'react';
30import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
31/* @info Import the ImagePicker */import * as ImagePicker from 'expo-image-picker';/* @end */
32
33export default function App() {
34  /* @info Launch the picker and log the result. */
35  let openImagePickerAsync = async () => {
36    let pickerResult = await ImagePicker.launchImageLibraryAsync();
37    console.log(pickerResult);
38  }
39  /* @end */
40
41  return (
42    <View style={styles.container}>
43      <Image source={{ uri: 'https://i.imgur.com/TkIrScD.png' }} style={styles.logo} />
44      <Text style={styles.instructions}>
45        To share a photo from your phone with a friend, just press the button below!
46      </Text>
47      <TouchableOpacity onPress={/* @info This function is a bit long so we moved it out to a variable */openImagePickerAsync/* @end */} style={styles.button}>
48        <Text style={styles.buttonText}>Pick a photo</Text>
49      </TouchableOpacity>
50    </View>
51  );
52}
53```
54
55</SnackInline>
56
57<br />
58
59You should see something like this when you run your app and use the picker:
60
61<Video file="tutorial/cli-logs.mp4" />
62
63> You can see the logs in your expo-cli terminal session or in the browser-based developer tools if you prefer it. To see the logs in Snack, press "Logs" in the footer.
64
65## Using the selected image
66
67Now we will take the data that we get from the image picker and use it to show the selected image in the app.
68
69<SnackInline label="Image picker show image" templateId="tutorial/image-picker-show" dependencies={['expo-image-picker']}>
70
71{/* prettier-ignore */}
72```js
73/* @info Import React to use useState */import React from 'react';/* @end */
74import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
75import * as ImagePicker from 'expo-image-picker';
76
77export default function App() {
78  /* @info Initialize a variable to hold our selected image data */const [selectedImage, setSelectedImage] = React.useState(null);/* @end */
79
80  let openImagePickerAsync = async () => {
81    let pickerResult = await ImagePicker.launchImageLibraryAsync();
82    /* @info Stop running the function here if the user cancelled the dialog */
83    if (pickerResult.cancelled === true) {
84      return;
85    }/* @end */
86    /* @info Store away the picked image uri */setSelectedImage({ localUri: pickerResult.uri });/* @end */
87  };
88
89  /* @info Show the selected image if we have one */
90  if (selectedImage !== null) {
91    return (
92      <View style={styles.container}>
93        <Image
94          source={{ uri: selectedImage.localUri }}
95          style={styles.thumbnail}
96        />
97      </View>
98    );
99  }/* @end */
100
101  return (
102    <View style={styles.container}>
103      {/* Our logo, instructions, and picker button are hidden here to keep the example brief */}
104    </View>
105  );
106}
107
108const styles = StyleSheet.create({
109  /* Other styles hidden to keep the example brief... */
110  /* @info We're giving the selected image a fixed width and height */
111  thumbnail: {
112    width: 300,
113    height: 300,
114    resizeMode: "contain"
115  }/* @end */
116});
117```
118
119</SnackInline>
120
121<br />
122
123Your app should now look and behave like this:
124
125<Video file="tutorial/picker-show.mp4" />
126
127> You might expect that because we gave our image an equal width and height it would be a square, but in the above video it's rectangular. This is because of `resizeMode`, an image style property that lets us control how the image is resized to fit the given dimensions. Try switching it from `contain` to `stretch` or `cover` to see other behaviors.
128
129We have made great progress! Up next, [let's make it possible to share the image](/tutorial/sharing).
130