Expo-camera onBarCodeScanned仅触发一次问题求助
问题根因
Expo Camera 原生层的条码扫描监听器,在onBarcodeScanned属性从函数切换为undefined、再切回函数的场景下,存在监听器未被正确重新绑定的残留bug,即便在标注已修复的Expo 45.0.6版本中,部分安卓、iOS机型上依然会复现首次扫码后监听失效的问题,本质是靠动态切换回调属性启停扫码的实现逻辑本身不稳定。
推荐解决方案
不要通过给onBarcodeScanned传undefined的方式解绑监听,改用JS层节流锁控制扫码结果的处理逻辑,全程给Camera传入稳定的回调引用,从根源上避免原生监听器的绑定/解绑操作。
- 用
useRef存储扫码锁定状态,修改ref值不会触发组件重渲染,也不会导致Camera组件的props发生变化 - 用
useCallback包裹扫码回调,保证回调引用全程稳定,原生层扫码监听器仅在组件挂载时初始化一次,不会出现重绑定失败的问题 - 扫码成功后先激活锁,拦截后续扫码结果,3秒冷却时间结束后自动解锁,恢复结果处理
对应实现代码:
import { useState, useRef, useCallback } from 'react'; import { View, Text } from 'react-native'; import { Camera } from 'expo-camera'; const QRScanner = () => { const [result, setResult] = useState('Nothing scanned yet'); // 扫码锁ref,初始为未锁定状态 const scanLockedRef = useRef(false); const scanHandler = useCallback(({ type, data }) => { // 锁激活时直接跳过结果处理 if (scanLockedRef.current) return; // 首次拿到结果后立刻上锁,避免重复触发 scanLockedRef.current = true; setResult(data); setTimeout(() => { // 3秒冷却结束后解锁,恢复扫码能力 scanLockedRef.current = false; }, 3000); }, []); return ( <View style={{flex: 1}}> <Camera style={{flex: 1}} // 始终传入稳定的回调引用,禁止传undefined触发原生监听解绑 onBarcodeScanned={scanHandler} > <Text>{result}</Text> </Camera> </View> ); }
备选方案(特殊场景使用)
如果业务场景需要在冷却期完全停止摄像头的扫码检测(不只是拦截JS层结果),可以通过给Camera组件加key属性的方式,在恢复扫码时强制组件重新挂载,彻底重置原生层状态:
import { useState } from 'react'; import { View, Text } from 'react-native'; import { Camera } from 'expo-camera'; const QRScanner = () => { const [scanned, setScanned] = useState(false); const [result, setResult] = useState('Nothing scanned yet'); const [cameraKey, setCameraKey] = useState(0); const scanHandler = ({type, data}) => { setScanned(true); setResult(data); setTimeout(() => { setScanned(false); // 递增key强制Camera重挂载,重置原生所有监听状态 setCameraKey(prev => prev + 1); }, 3000); } return ( <View style={{flex: 1}}> <Camera key={cameraKey} style={{flex: 1}} onBarcodeScanned={scanned ? undefined : scanHandler} > <Text>{result}</Text> </Camera> </View> ) }
注意:该方案会触发相机重新初始化,可能出现短暂黑屏,体验弱于第一种锁方案,非必要不使用。
内容的提问来源于stack exchange,提问作者mvioole
相关产品推荐
相关产品推荐

