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

React Native Vision Camera返回时出现View Manager错误原因排查

问题:返回相机页面时出现「View Manager for tag」错误

用户点击按钮导航至新页面,该页面通过React Native Vision Camera打开相机,但按下返回按钮时未回到前一页,反而弹出「View Manager for tag could not be found」错误。

相关代码

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

问题原因及解决方案

  1. 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]);
    
  2. 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
    
  3. 导航生命周期处理不当
    用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:08:12