Almost every app eventually needs a way to pick a profile photo, attach an image, or upload a video. expo-image-picker opens the system's native media UI so users can choose from their library or shoot something new — and it's consistently one of the most-searched Expo modules. Here's how to use it end-to-end.
Install
npx expo install expo-image-picker
Add permission copy via the config plugin in app.json:
{
"expo": {
"plugins": [
["expo-image-picker", {
"photosPermission": "Allow $(PRODUCT_NAME) to access your photos."
}]
]
}
}
Pick an image from the library
import * as ImagePicker from "expo-image-picker"
import { useState } from "react"
import { Button, Image, View } from "react-native"
export default function Picker() {
const [uri, setUri] = useState<string | null>(null)
async function pick() {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ["images"],
allowsEditing: true,
aspect: [1, 1],
quality: 0.8,
})
if (!result.canceled) {
setUri(result.assets[0].uri)
}
}
return (
<View style={{ gap: 12, padding: 24 }}>
<Button title="Pick a photo" onPress={pick} />
{uri && <Image source={{ uri }} style={{ width: 200, height: 200, borderRadius: 12 }} />}
</View>
)
}
Note the modern API uses mediaTypes: ["images"] (an array of strings) — the old MediaTypeOptions enum is deprecated.
Take a new photo instead
Same options, but launch the camera:
const result = await ImagePicker.launchCameraAsync({
mediaTypes: ["images"],
quality: 0.8,
})
launchCameraAsync requires camera permission — request it first with ImagePicker.requestCameraPermissionsAsync().
Allow multiple selection
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ["images", "videos"],
allowsMultipleSelection: true,
selectionLimit: 5,
})
// result.assets is now an array of everything the user picked
Upload the picked file
Turn the asset into FormData and POST it:
async function upload(uri: string) {
const form = new FormData()
form.append("file", {
uri,
name: "upload.jpg",
type: "image/jpeg",
} as any)
await fetch("https://your-api.com/upload", { method: "POST", body: form })
}
Gotchas
- Always check
result.canceledbefore touchingresult.assets— the user may back out. qualityis 0–1; lower it to shrink upload sizes.- To render picked images faster in long lists, swap React Native's
Imagefor expo-image.
Next steps
Want to capture instead of pick? See the expo-camera tutorial. To store uploaded file references offline, check expo-sqlite or the full top 10 Expo SDK modules.