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

React模态框中使用react-qr-barcode-scanner实现扫码功能异常问题排查

问题根源分析

你的问题核心在于Bootstrap模态框初始状态是隐藏的:当QR组件在隐藏的模态框内挂载时,react-qr-barcode-scanner会尝试初始化摄像头并渲染视频元素,但此时视频容器处于display: none的不可见状态,浏览器会限制摄像头的访问权限,或者组件无法正确完成视频流的初始化,最终导致扫码功能失效。

另外你的useEffect还存在一个小问题:没有设置依赖数组,这会导致组件每次渲染时都触发这个副作用,进而引发不必要的路由跳转循环;而且history.go()是多余的,history.push()已经会触发路由更新。


解决方案

我们可以通过监听Bootstrap模态框的显示事件,在模态框完全显示后再挂载扫码组件,确保视频元素可见时才初始化摄像头。同时修复useEffect的依赖问题。

步骤1:修改主组件,添加模态框显示监听

用状态控制QR组件的渲染,只有当模态框显示后才渲染它:

import React, { useEffect, useState} from "react";
import ReactDOM from 'react-dom';
import { useHistory, BrowserRouter } from "react-router-dom";
import BarcodeScannerComponent from "react-qr-barcode-scanner";

const QR = () => {
  const [data, setData ] = useState('Not Found');
  const history = useHistory();

  // 修复useEffect依赖,仅在data变化时触发
  useEffect(() => {
    if(data !== 'Not Found') {
      history.push(data);
      // 移除多余的history.go()
    }
  }, [data, history]) // 添加依赖数组

  return (
    <>
      <BarcodeScannerComponent
        width={500}
        height={500}
        onUpdate={(err, result) => {
          if (result) {
            setData(result.text);
          } else setData("Not Found");
        }}
      />
      <p>{data}</p>
    </>
  );
}

const App = () => {
  const [modalShown, setModalShown] = useState(false);

  useEffect(() => {
    // 监听Bootstrap模态框的显示/隐藏事件
    const modalElement = document.getElementById('qr-modal');
    const handleModalShown = () => setModalShown(true);
    const handleModalHidden = () => setModalShown(false);

    modalElement.addEventListener('shown.bs.modal', handleModalShown);
    modalElement.addEventListener('hidden.bs.modal', handleModalHidden);

    // 组件卸载时清理监听
    return () => {
      modalElement.removeEventListener('shown.bs.modal', handleModalShown);
      modalElement.removeEventListener('hidden.bs.modal', handleModalHidden);
    };
  }, []);

  return (
    <>
      <button type="button" className="btn btn-primary" data-toggle="modal" data-target="#qr-modal">
        <i className="fas fa-qrcode"></i>
      </button>
      <div className="modal fade" id="qr-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
        <div className="modal-dialog" role="document">
          <div className="modal-content">
            <div className="modal-header">
              <h5 className="modal-title" id="exampleModalLabel">扫码跳转</h5>
              <button type="button" className="close" data-dismiss="modal" aria-label="Close">
                <span aria-hidden="true">&times;</span>
              </button>
            </div>
            <div className="modal-body">
              {/* 仅在模态框完全显示后才渲染扫码组件 */}
              {modalShown && <QR />}
            </div>
            <div className="modal-footer">
              <button type="button" className="btn btn-secondary" data-dismiss="modal">Close</button>
            </div>
          </div>
        </div>
      </div>
    </>
  )
}

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('qr-id')
);

关键修改点说明:

  1. 模态框显示监听:通过Bootstrap的shown.bs.modal事件判断模态框是否完全显示,此时再渲染QR组件,确保扫码组件初始化时视频元素是可见的,浏览器能正常授予摄像头权限。
  2. 修复useEffect依赖:给useEffect添加[data, history]依赖数组,避免不必要的重复触发;同时移除了多余的history.go()。
  3. 规范React属性写法:将class改为React标准的className属性,避免潜在的兼容性问题。

内容的提问来源于stack exchange,提问作者Áron Pop Adorján

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 04:47:35