Expo SDK 52中Camera组件报错,SDK51正常,求修复方案
解决Expo SDK52升级后Element type invalid错误
问题概述
SDK51正常运行的相机应用,升级到SDK52后抛出错误:
ERROR Warning: Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object
相关代码如下:
App.js
import React, { useState, useEffect, useRef } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native'; import { Camera } from 'expo-camera'; export default function App() { const [hasPermission, setHasPermission] = useState(null); const [capturedImage, setCapturedImage] = useState(null); const cameraRef = useRef(null); useEffect(() => { (async () => { const { status } = await Camera.requestCameraPermissionsAsync(); setHasPermission(status === 'granted'); })(); }, []); const takePicture = async () => { if (cameraRef.current) { const photo = await cameraRef.current.takePictureAsync(); setCapturedImage(photo.uri); } }; return ( <View style={styles.container}> {capturedImage ? ( <View style={styles.imageContainer}> <Image source={{ uri: capturedImage }} style={styles.capturedImage} /> {/* Add a button to re-take the picture or process the image */} </View> ) : ( <View style={styles.cameraContainer}> <Camera style={styles.camera} ref={cameraRef} /> <TouchableOpacity style={styles.button} onPress={takePicture}> <Text style={styles.buttonText}>Take Picture</Text> </TouchableOpacity> </View> )} </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, camera: { flex: 1, }, button: { backgroundColor: '#fff', paddingHorizontal: 20, paddingVertical: 10, borderRadius: 10, }, buttonText: { fontSize: 16, fontWeight: 'bold', }, imageContainer: { flex: 1, alignItems: 'center', justifyContent: 'center', }, capturedImage: { width: 300, height: 200, }, });
package.json
{ "name": "cameraapp", "license": "0BSD", "version": "1.0.0", "main": "index.js", "scripts": { "start": "expo start", "android": "expo start --android", "ios": "expo start --ios", "web": "expo start --web" }, "dependencies": { "@expo/metro-runtime": "~4.0.0", "axios": "^1.7.7", "expo": "^52.0.7", "expo-camera": "~16.0.5", "expo-image-manipulator": "~13.0.5", "expo-image-picker": "~16.0.2", "expo-status-bar": "~2.0.0", "expo-web-browser": "~14.0.1", "firebase": "^11.0.2", "react": "18.3.1", "react-dom": "18.3.1", "react-native": "^0.76.2", "react-native-web": "~0.19.13", "react-webcam": "^7.2.0" }, "devDependencies": { "@babel/core": "^7.20.0", "@react-native-community/cli": "latest" }, "private": true, "expo": { "doctor": { "reactNativeDirectoryCheck": { "exclude": ["firebase", "react-webcam", "@expo/metro-runtime"] } } } }
修复步骤
1. 调整expo-camera的导入与权限方法
SDK52配套的expo-camera@16.x重构了API,原命名导入不再生效,且权限方法名变更:
- 将导入语句从
import { Camera } from 'expo-camera';改为:import Camera from 'expo-camera'; - 将权限申请方法
Camera.requestCameraPermissionsAsync()替换为:const { status } = await Camera.requestPermissionsAsync();
2. 移除冲突依赖
react-webcam是Web专用组件,与Expo原生环境不兼容,直接卸载并从package.json中删除:
npm uninstall react-webcam
3. 降级firebase到稳定版
firebase@11.x为测试版,可能与SDK52存在适配问题,建议降级到稳定版:
npm install firebase@10.12.5
4. 清理缓存重启项目
修改完成后,清理Expo缓存并重启确保生效:
expo r -c
验证修改后的核心代码
import React, { useState, useEffect, useRef } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native'; import Camera from 'expo-camera'; export default function App() { const [hasPermission, setHasPermission] = useState(null); const [capturedImage, setCapturedImage] = useState(null); const cameraRef = useRef(null); useEffect(() => { (async () => { const { status } = await Camera.requestPermissionsAsync(); setHasPermission(status === 'granted'); })(); }, []); const takePicture = async () => { if (cameraRef.current) { const photo = await cameraRef.current.takePictureAsync(); setCapturedImage(photo.uri); } }; return ( <View style={styles.container}> {capturedImage ? ( <View style={styles.imageContainer}> <Image source={{ uri: capturedImage }} style={styles.capturedImage} /> </View> ) : ( <View style={styles.cameraContainer}> <Camera style={styles.camera} ref={cameraRef} /> <TouchableOpacity style={styles.button} onPress={takePicture}> <Text style={styles.buttonText}>Take Picture</Text> </TouchableOpacity> </View> )} </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, camera: { flex: 1, }, button: { backgroundColor: '#fff', paddingHorizontal: 20, paddingVertical: 10, borderRadius: 10, }, buttonText: { fontSize: 16, fontWeight: 'bold', }, imageContainer: { flex: 1, alignItems: 'center', justifyContent: 'center', }, capturedImage: { width: 300, height: 200, }, });
内容的提问来源于stack exchange,提问作者geeeeen
相关产品推荐
相关产品推荐

