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

如何为Expo Camera的二维码扫描添加合理的扫描间隔?

解决Expo Camera重复扫描二维码触发多次认证请求的问题

问题分析

你的核心问题是相机持续识别同一二维码,导致onBarcodeScanned被频繁触发——即使加了延迟也只是推迟了请求执行,没有阻止相机的重复扫描检测。同时当前逻辑在认证失败后没有重置扫描状态,无法重新发起扫描。

解决方案

通过引入处理中状态来控制扫描触发时机,确保同一时间只有一个认证请求在处理,并且在认证失败后重置状态允许重新扫描:

修改后的代码

import React, { useState } from "react";
import { View, Text, TouchableOpacity, StyleSheet, Button, ActivityIndicator } from "react-native";
import { CameraView, useCameraPermissions } from "expo-camera";
import { auth } from "../../firebase/firebaseConfig";
import { signInWithCustomToken } from "firebase/auth";

const QRcodeScan = ({ navigation }) => {
  const [scanned, setScanned] = useState(false);
  // 新增状态:标记是否正在处理认证请求
  const [isProcessing, setIsProcessing] = useState(false);

  const handleBarcodeScanned = async (scannedData) => {
    console.log("Scanned token:", scannedData);
    try {
      const userCredential = await signInWithCustomToken(auth, scannedData);
      console.log("Signed in successfully as:", userCredential.user.uid);
      navigation.navigate("ProfileSelection");
    } catch (error) {
      console.error("Error signing in with custom token:", error);
      // 认证失败后,重置状态允许重新扫描
      setScanned(false);
      setIsProcessing(false);
    }
  };

  return (
    <View style={styles.container}>
      <CameraView
        style={styles.camera}
        facing={facing}
        onBarcodeScanned={({ data }) => {
          // 只有当未扫描过、未在处理中且有有效数据时,才启动认证流程
          if (data && !scanned && !isProcessing) {
            setScanned(true);
            setIsProcessing(true);
            handleBarcodeScanned(data);
          }
        }}
      >
        {/* 可选:添加加载提示,提升用户体验 */}
        {isProcessing && (
          <View style={styles.loadingOverlay}>
            <ActivityIndicator size="large" color="#fff" />
            <Text style={styles.loadingText}>正在验证...</Text>
          </View>
        )}
        {/* Rest of the code */}
      </CameraView>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
  },
  camera: {
    flex: 1,
    width: "100%",
    position: "relative",
  },
  loadingOverlay: {
    position: "absolute",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: "rgba(0,0,0,0.7)",
    justifyContent: "center",
    alignItems: "center",
  },
  loadingText: {
    color: "#fff",
    marginTop: 16,
    fontSize: 16,
  },
});

export default QRcodeScan;

关键改动说明

  • 新增isProcessing状态:彻底阻止相机在认证请求未完成时重复触发扫描逻辑。
  • 严格控制触发条件:只有当存在有效扫描数据、未扫描过且不在处理中时,才启动认证流程。
  • 失败后重置状态:在catch块中将scanned和isProcessing设为false,允许用户重新扫描。
  • 移除不必要的setTimeout:延迟无法阻止重复扫描,直接同步触发认证即可。

额外优化建议

  • 可以对扫描到的scannedData做短时间缓存,避免同一二维码被重复处理。
  • 若二维码可能过期,可在认证失败时提示用户二维码无效或已过期。

内容的提问来源于stack exchange,提问作者Development DOEdeal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 06:42:45