React项目中使用QrReader无法切换前后置摄像头的问题求助
二维码扫描摄像头切换功能修复求助
这是我目标功能的示例演示。如果有人知道如何修复使其正常工作或有新的实现思路,欢迎分享。
本演示基于QrReader实现,我希望调用设备上的摄像头,并根据用户选择切换用于扫描二维码的摄像头。以下是我的代码,提前感谢各位的帮助。
import React, { useState, useRef, useEffect } from 'react'; import { QrReader } from 'react-qr-reader'; import './estilos.css'; function Lector() { const [qrCodeData, setQrCodeData] = useState(null); const [activate, setActivate] = useState(false); const [facingMode, setFacingMode] = useState('environment'); const qrReaderRef = useRef(null); const [cameras, setCameras] = useState([]); useEffect(() => { navigator.mediaDevices.enumerateDevices().then((devices) => { const videoDevices = devices.filter((device) => device.kind === 'videoinput'); setCameras(videoDevices); }); }, []); const handleQRCodeScan = (data) => { if (data) { setQrCodeData(data); setActivate(true); } }; const ventana = () => { window.open(qrCodeData); }; const ventana2 = () => { window.open('https://qr.primerosauxilios.online/', '_top'); }; const handleCameraChange = (event) => { setFacingMode(event.target.value); }; return ( <article className="card"> <button onClick={ventana2} style={{ cursor: 'pointer', background: 'orange' }}> Generar QR </button> <select name="select" onChange={handleCameraChange}> {cameras.map((camera) => ( <option key={camera.deviceId} value={camera.deviceId}> {camera.label || `Camera ${camera.deviceId}`} </option> ))} </select> <div className="qr-box" style={{ background: 'black', position: 'relative' }}> <div style={{ width: '300px', height: '300px' }}> <QrReader ref={qrReaderRef} style={{ width: '100%' }} onResult={(result, error) => { if (result) { handleQRCodeScan(result.text); } if (error) { console.info(error); } }} facingMode={facingMode} /> <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', border: '3px solid blue', width: '200px', height: '200px', }} ></div> </div> </div> <p>Resultado del QR: {qrCodeData}</p> {activate ? ( <button onClick={ventana} style={{ cursor: 'pointer', background: 'black', color: 'white' }} > Abrir </button> ) : ( <button disabled style={{ background: 'red', color: 'white' }}> Esperando Link </button> )} </article> ); } export default Lector;
修复方案
核心问题
代码中facingMode的传值方式错误:当指定具体设备ID时,react-qr-reader要求传入{ exact: 设备ID }格式的对象,而非直接传入设备ID字符串。此外,部分浏览器需要先获取摄像头权限,才能返回设备的真实标签名称(如“后置摄像头”)。
修改步骤
调整摄像头切换逻辑:
修改handleCameraChange函数,将facingMode设置为包含设备ID的对象:const handleCameraChange = (event) => { setFacingMode({ exact: event.target.value }); };确保设备标签正常显示:
在获取设备列表前先请求摄像头权限,避免仅显示设备ID:useEffect(() => { const getDevices = async () => { // 请求摄像头权限,确保能获取到设备真实标签 await navigator.mediaDevices.getUserMedia({ video: true }); const devices = await navigator.mediaDevices.enumerateDevices(); const videoDevices = devices.filter(device => device.kind === 'videoinput'); setCameras(videoDevices); }; getDevices(); }, []);强制组件重新挂载(可选):
给QrReader添加key属性,值为facingMode的JSON字符串,确保切换摄像头时组件重新初始化:<QrReader key={JSON.stringify(facingMode)} ref={qrReaderRef} style={{ width: '100%' }} onResult={(result, error) => { if (result) { handleQRCodeScan(result.text); } if (error) { console.info(error); } }} facingMode={facingMode} />
修改后的完整代码
import React, { useState, useRef, useEffect } from 'react'; import { QrReader } from 'react-qr-reader'; import './estilos.css'; function Lector() { const [qrCodeData, setQrCodeData] = useState(null); const [activate, setActivate] = useState(false); const [facingMode, setFacingMode] = useState('environment'); const qrReaderRef = useRef(null); const [cameras, setCameras] = useState([]); useEffect(() => { const getDevices = async () => { // 请求摄像头权限,确保能获取到设备真实标签 await navigator.mediaDevices.getUserMedia({ video: true }); const devices = await navigator.mediaDevices.enumerateDevices(); const videoDevices = devices.filter(device => device.kind === 'videoinput'); setCameras(videoDevices); }; getDevices(); }, []); const handleQRCodeScan = (data) => { if (data) { setQrCodeData(data); setActivate(true); } }; const ventana = () => { window.open(qrCodeData); }; const ventana2 = () => { window.open('https://qr.primerosauxilios.online/', '_top'); }; const handleCameraChange = (event) => { setFacingMode({ exact: event.target.value }); }; return ( <article className="card"> <button onClick={ventana2} style={{ cursor: 'pointer', background: 'orange' }}> Generar QR </button> <select name="select" onChange={handleCameraChange}> {cameras.map((camera) => ( <option key={camera.deviceId} value={camera.deviceId}> {camera.label || `Camera ${camera.deviceId}`} </option> ))} </select> <div className="qr-box" style={{ background: 'black', position: 'relative' }}> <div style={{ width: '300px', height: '300px' }}> <QrReader key={JSON.stringify(facingMode)} ref={qrReaderRef} style={{ width: '100%' }} onResult={(result, error) => { if (result) { handleQRCodeScan(result.text); } if (error) { console.info(error); } }} facingMode={facingMode} /> <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', border: '3px solid blue', width: '200px', height: '200px', }} ></div> </div> </div> <p>Resultado del QR: {qrCodeData}</p> {activate ? ( <button onClick={ventana} style={{ cursor: 'pointer', background: 'black', color: 'white' }} > Abrir </button> ) : ( <button disabled style={{ background: 'red', color: 'white' }}> Esperando Link </button> )} </article> ); } export default Lector;
内容的提问来源于stack exchange,提问作者Jack K3v1n Páramo
相关产品推荐
相关产品推荐

