如何避免使用react-navigation时expo-camera每次渲染都重新配置
核心问题分析
相机每次重启的根源是:MainScreen因faceData更新重渲染时,Camera组件的某些props(比如faceDetectorSettings)每次都生成新的对象,React判断props变化后会触发组件的重新卸载与挂载,进而导致相机重启。
具体解决方案
1. 缓存静态配置props,避免不必要的组件更新
如果camSett是静态配置(不会随组件状态变化),直接将其定义在组件外部,或用useMemo缓存,确保每次渲染时faceDetectorSettings传递的是同一个引用:
import { Camera } from 'expo-camera'; import { useState, useMemo } from 'react'; // 静态配置直接放在组件外,避免每次渲染重建对象 const camSett = { mode: Camera.Constants.FaceDetector.Mode.fast, detectLandmarks: Camera.Constants.FaceDetector.Landmarks.none, runClassifications: Camera.Constants.FaceDetector.Classifications.none, minDetectionInterval: 500, // 可调整检测间隔,减少触发频率 }; function MainScreen({ navigation }) { const [faceData, setFaceData] = useState([]); // 缓存faceDetectorSettings,确保引用稳定 const faceDetectorSettings = useMemo(() => ({ camSett }), []); return ( <Camera ref={CAM} style={CSS.cameraStyle} type={Camera.Constants.Type.front} faceDetectorSettings={faceDetectorSettings} onFacesDetected={(e) => setFaceData(e.faces)} > {doSomeWith(faceData)} </Camera> ); };
2. 优化人脸检测回调,减少无意义的state更新
通过对比新旧人脸数据,仅当内容真正变化时才更新faceData,避免不必要的重渲染:
import { Camera } from 'expo-camera'; import { useState, useMemo, useCallback } from 'react'; const camSett = { /* 静态配置 */ }; function MainScreen({ navigation }) { const [faceData, setFaceData] = useState([]); const faceDetectorSettings = useMemo(() => ({ camSett }), []); // 仅当人脸数据变化时更新state const handleFacesDetected = useCallback((e) => { const newFaces = e.faces; if (JSON.stringify(newFaces) !== JSON.stringify(faceData)) { setFaceData(newFaces); } }, [faceData]); return ( <Camera ref={CAM} style={CSS.cameraStyle} type={Camera.Constants.Type.front} faceDetectorSettings={faceDetectorSettings} onFacesDetected={handleFacesDetected} > {doSomeWith(faceData)} </Camera> ); };
3. 将Camera封装为独立子组件,用React.memo隔离渲染
把Camera相关逻辑抽成单独的子组件,并用React.memo包裹,只有当子组件的props真正变化时才会重渲染,避免受父组件其他无关更新影响:
import { Camera } from 'expo-camera'; import { useState, useMemo, useCallback, memo } from 'react'; const camSett = { /* 静态配置 */ }; // 用memo包裹子组件,仅在props变化时重渲染 const CameraView = memo(({ onFacesDetected, children }) => { const faceDetectorSettings = useMemo(() => ({ camSett }), []); return ( <Camera ref={CAM} style={CSS.cameraStyle} type={Camera.Constants.Type.front} faceDetectorSettings={faceDetectorSettings} onFacesDetected={onFacesDetected} > {children} </Camera> ); }); function MainScreen({ navigation }) { const [faceData, setFaceData] = useState([]); const handleFacesDetected = useCallback((e) => { const newFaces = e.faces; if (JSON.stringify(newFaces) !== JSON.stringify(faceData)) { setFaceData(newFaces); } }, [faceData]); return ( <CameraView onFacesDetected={handleFacesDetected}> {doSomeWith(faceData)} </CameraView> ); };
内容的提问来源于stack exchange,提问作者EnzoBH
相关产品推荐
相关产品推荐

