You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 04:17:34