React Native Vision Camera返回时出现View Manager错误原因排查
用户点击按钮导航至新页面,该页面通过React Native Vision Camera打开相机,但按下返回按钮时未回到前一页,反而弹出「View Manager for tag
相关代码
const [hasPermission, setHasPermission] = useState(false); const [barcodes, setBc] = useState([]); const [isActive, setActive] = useState(true); const devices = useCameraDevices(); const device = devices.back; const navigation = useNavigation(); function scanBarcodes(frame, types, options) { 'worklet'; return __scanCodes(frame, types, options); } const frameProcessor = useFrameProcessor((frame) => { 'worklet'; const detectedBarcodes = scanBarcodes(frame, [BarcodeFormat.QR_CODE], { checkInverted: true }); runOnJS(setBc)(detectedBarcodes); }, []); useEffect(() => { (async () => { let granted = await Permission.checkPermission(PERMISSION_TYPE.camera); if (!granted) { granted = await Permission.requestPermission(PERMISSION_TYPE.camera); } setHasPermission(granted); })(); }, []); useEffect(() => { const unsubscribe = navigation.addListener('beforeRemove', () => { setHasPermission(false); setBc([]); setActive(false); }); return unsubscribe; }, [navigation]); const onSuccess = (e) => {}; if (device != null && hasPermission) { return ( <> <Camera style={StyleSheet.absoluteFill} device={device} isActive={isActive} frameProcessor={frameProcessor} frameProcessorFps={5} /> {barcodes.map((barcode, idx) => ( <Text key={idx} style={styles.barcodeTextURL}> {barcode.displayValue} </Text> ))} </> ); } else { return ( <View> <Text>Need Permission</Text> </View> ); }
错误信息
弹出错误提示:View Manager for tag <XXX> could not be found,提示原生视图管理器无法找到对应标签的组件。
使用的依赖版本
- react-native-reanimated: 2.3.0-alpha.3
- react-native-vision-camera: 2.13.0
- vision-camera-code-scanner: ^0.2.0
问题原因及解决方案
Frame Processor 未彻底清理
页面卸载时,你只停止了相机(设置isActive为false),但frameProcessor作为Reanimated worklet仍在后台运行,原生端持续尝试调用已销毁的RN组件方法,导致桥接异常。解决:将frameProcessor存入state,页面卸载时清空它:
// 初始化时将frameProcessor存入state const [frameProcessor, setFrameProcessor] = useState(() => useFrameProcessor((frame) => { 'worklet'; const detectedBarcodes = scanBarcodes(frame, [BarcodeFormat.QR_CODE], { checkInverted: true }); runOnJS(setBc)(detectedBarcodes); }, []) ); // 修改beforeRemove监听 useEffect(() => { const unsubscribe = navigation.addListener('beforeRemove', () => { setActive(false); setBc([]); setFrameProcessor(null); // 清空frameProcessor }); return unsubscribe; }, [navigation]);Reanimated版本兼容性问题
你使用的Reanimated是测试版(2.3.0-alpha.3),和Vision Camera 2.13.0存在版本适配问题。Vision Camera 2.x系列要求Reanimated使用2.8+的稳定版本。解决:升级Reanimated到稳定版:
npm install react-native-reanimated@2.10.0 # iOS需重新执行pod install导航生命周期处理不当
用beforeRemove监听修改hasPermission状态,会触发组件重新渲染,但此时页面已进入卸载流程,状态更新会导致原生视图和RN逻辑不同步。解决:移除
setHasPermission(false),仅保留相机停止和资源清理逻辑;或改用useFocusEffect管理相机激活状态,更贴合导航生命周期:import { useFocusEffect } from '@react-navigation/native'; useFocusEffect( React.useCallback(() => { setActive(true); return () => { setActive(false); setFrameProcessor(null); }; }, []) );
内容的提问来源于stack exchange,提问作者Tanvir Rahman

