使用Expo React Native集成react-native-vision-camera遇相机启动错误求助
解决React Native Expo中react-native-vision-camera的
getAvailableCameraDevices为null的问题 错误原因分析
TypeError: Cannot read property 'getAvailableCameraDevices' of null 本质是相机模块在未获取到权限的情况下尝试访问设备列表,或是权限请求逻辑未正确执行导致相机模块未完成初始化。
具体修复步骤
1. 修复权限请求的执行逻辑
你的useEffect里仅引用了requestCameraPermission变量,没有实际调用该函数,导致权限根本没发起请求。同时要确保useEffect的依赖数组包含这个回调函数:
React.useEffect(()=>{ requestCameraPermission(); // 加上()执行函数 },[requestCameraPermission]) // 添加依赖确保回调更新时重新执行
2. 新增权限状态跟踪,避免提前初始化相机
添加状态变量记录权限状态,只有当权限通过后再渲染相机相关逻辑,避免useCameraDevices在权限未就绪时执行:
const [hasCameraPermission, setHasCameraPermission] = React.useState(false); // 修改权限请求回调,更新权限状态 const requestCameraPermission = React.useCallback(async ()=>{ const permission = await Camera.requestCameraPermission(); if(permission === 'granted'){ setHasCameraPermission(true); } else if(permission === 'denied'){ await Linking.openSettings() } },[])
3. 调整相机初始化逻辑,依赖权限状态
仅当hasCameraPermission为true时,才调用useCameraDevices,同时使用可选链避免null报错:
const devices = hasCameraPermission ? useCameraDevices('wide-angle-camera') : null; const device = devices?.back;
4. 配置Expo权限声明
在项目根目录的app.json中添加相机权限描述,iOS必须配置NSCameraUsageDescription,Android需要添加CAMERA权限:
{ "expo": { "ios": { "infoPlist": { "NSCameraUsageDescription": "需要访问相机进行产品扫描" } }, "android": { "permissions": ["CAMERA"] } } }
修改后的完整代码
import React from 'react'; import { View, Linking } from 'react-native'; import { Camera, useCameraDevices } from 'react-native-vision-camera'; const ScanProduct =({navigation})=>{ const [hasCameraPermission, setHasCameraPermission] = React.useState(false); // 仅当权限通过后才获取相机设备 const devices = hasCameraPermission ? useCameraDevices('wide-angle-camera') : null; const device = devices?.back; React.useEffect(()=>{ requestCameraPermission(); },[requestCameraPermission]) const requestCameraPermission = React.useCallback(async ()=>{ const permission = await Camera.requestCameraPermission(); if(permission === 'granted'){ setHasCameraPermission(true); } else if(permission === 'denied'){ await Linking.openSettings() } },[]) function renderCamera(){ if(device == null){ return( <View style={{flex:1}}/> ) } else{ return( <View style={{flex:1}}> <Camera style={{flex:1}} device={device} isActive={true} enableZoomGesture /> </View> ) } } return( <View style={{flex:1}}> {hasCameraPermission && renderCamera()} </View> ) } export default ScanProduct;
额外注意事项
- 确保
react-native-vision-camera版本与当前Expo SDK兼容,部分高版本的vision-camera可能需要使用Expo Dev Client而非Expo Go(Expo Go不支持自定义原生模块配置),如果上述修复后仍有问题,可以尝试切换到Expo Dev Client测试。 - iOS上第一次拒绝权限后,再次请求会直接跳转设置页面,你的代码已处理该逻辑,无需额外修改。
内容的提问来源于stack exchange,提问作者Bashamlan Salem
相关产品推荐
相关产品推荐

