Expo启动App遇TypeError:无法读取null的launchImageLibrary属性
问题:使用
npx expo start启动应用时出现TypeError: Cannot read property "launchImageLibrary" of null错误 错误信息
Console Warning : Possible unhandled promise rejection (id:0):
TypeError: Cannot read property "launchImageLibrary" of null
相关代码
UploadScreen.tsx
import React, { useState } from 'react'; import { StyleSheet, View, Text, Button, Image } from 'react-native'; import { launchCamera, launchImageLibrary } from 'react-native-image-picker'; import { StackNavigationProp } from '@react-navigation/stack'; import { YourStackParamList } from '../type'; type HomeScreenProps = { navigation: StackNavigationProp<YourStackParamList, 'Home'>; }; function UploadScreen({ navigation }: HomeScreenProps) { const [imageUri, setImageUri] = useState<string | null>(null); const openImagePicker = async () => { const result = await launchImageLibrary({ mediaType: 'photo', quality: 1, }); if (result.assets && result.assets.length > 0 && result.assets[0].uri) { setImageUri(result.assets[0].uri); } else { setImageUri(null); } }; const openCamera = async () => { const result = await launchCamera({ mediaType: 'photo', cameraType: 'back', quality: 1, }); if (result.assets && result.assets.length > 0 && result.assets[0].uri) { setImageUri(result.assets[0].uri); } else { setImageUri(null); } }; return ( <View style={styles.container}> <Text style={styles.text}> Upload</Text> <Button title="Sélectionner depuis la galerie" onPress={openImagePicker} /> <Button title="Prendre une photo" onPress={openCamera} /> {imageUri && <Image source={{ uri: imageUri }} style={styles.image} />} </View> ); } export default UploadScreen; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, text: { color: '#0C1947', fontSize: 20, marginBottom: 20, }, image: { width: 300, height: 300, marginTop: 20, }, });
app.json
{ "expo": { "name": "oysterCVApp", "slug": "oysterCVApp", "version": "1.0.0", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "light", "splash": { "image": "./assets/splash.png", "resizeMode": "contain", "backgroundColor": "#ffffff" }, "assetBundlePatterns": ["**/*"], "ios": { "supportsTablet": true, "infoPlist": { "NSCameraUsageDescription": "Cette application a besoin d'accéder à la caméra pour prendre des photos.", "NSPhotoLibraryUsageDescription": "Cette application a besoin d'accéder à la bibliothèque de photos pour sélectionner des images.", "NSPhotoLibraryAddUsageDescription": "Cette application a besoin d'ajouter des images à la bibliothèque de photos." } }, "android": { "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" }, "permissions": ["CAMERA", "READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE"] }, "web": { "favicon": "./assets/favicon.png" } } }
package.json
{ "name": "oystercvapp", "version": "1.0.0", "scripts": { "start": "npx expo start src/App.tsx", "android": "expo start --android", "ios": "expo start --ios", "web": "expo start --web" }, "dependencies": { "@react-navigation/native": "^6.1.9", "@react-navigation/native-stack": "^6.9.17", "@react-navigation/stack": "^6.3.20", "expo": "~50.0.6", "expo-permissions": "^14.4.0", "expo-status-bar": "~1.11.1", "react": "18.2.0", "react-native": "0.73.4", "react-native-image-picker": "^7.1.0" }, "devDependencies": { "@babel/core": "^7.20.0", "@types/react": "~18.2.45", "@types/react-native": "^0.73.0", "typescript": "^5.1.3" }, "private": true }
复现步骤
- 使用
npx expo start启动应用 - 导航至上传页面
- 尝试从图库选择图片或拍照
预期行为
应用应允许用户无错误地从图库选图或拍照
补充说明
已在app.json中配置了访问相机和图库的必要权限,且已确认react-native-image-picker已正确安装并更新至最新版本。
解决方案
问题根源
react-native-image-picker是原生React Native模块,无法在Expo Go环境中直接使用——Expo有专属的图片选择库expo-image-picker,两者API不兼容,导致调用时出现null引用错误。
修复步骤
替换依赖库
卸载react-native-image-picker,安装expo-image-picker:npm uninstall react-native-image-picker npx expo install expo-image-picker修改UploadScreen.tsx代码
替换导入并适配expo-image-picker的API:import React, { useState } from 'react'; import { StyleSheet, View, Text, Button, Image } from 'react-native'; import * as ImagePicker from 'expo-image-picker'; import { StackNavigationProp } from '@react-navigation/stack'; import { YourStackParamList } from '../type'; type HomeScreenProps = { navigation: StackNavigationProp<YourStackParamList, 'Home'>; }; function UploadScreen({ navigation }: HomeScreenProps) { const [imageUri, setImageUri] = useState<string | null>(null); const openImagePicker = async () => { // 请求图库权限 const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (!permissionResult.granted) { alert("需要授予图库访问权限"); return; } const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, quality: 1, }); if (!result.canceled && result.assets[0].uri) { setImageUri(result.assets[0].uri); } else { setImageUri(null); } }; const openCamera = async () => { // 请求相机权限 const permissionResult = await ImagePicker.requestCameraPermissionsAsync(); if (!permissionResult.granted) { alert("需要授予相机访问权限"); return; } const result = await ImagePicker.launchCameraAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, quality: 1, }); if (!result.canceled && result.assets[0].uri) { setImageUri(result.assets[0].uri); } else { setImageUri(null); } }; return ( <View style={styles.container}> <Text style={styles.text}> Upload</Text> <Button title="Sélectionner depuis la galerie" onPress={openImagePicker} /> <Button title="Prendre une photo" onPress={openCamera} /> {imageUri && <Image source={{ uri: imageUri }} style={styles.image} />} </View> ); } export default UploadScreen; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, text: { color: '#0C1947', fontSize: 20, marginBottom: 20, }, image: { width: 300, height: 300, marginTop: 20, }, });清理并重启服务
清除Expo缓存后重启应用:npx expo start --clear
额外说明
expo-permissions已被废弃,expo-image-picker自带权限请求方法,无需额外依赖。- 你已在app.json中配置的权限描述会被Expo自动识别,无需额外修改。
内容的提问来源于stack exchange,提问作者Zway
相关产品推荐
相关产品推荐

