Yes, a component that does the job well. Code below, customise for your use case.
Note: It does not use the “cordova-plugin-qrscanner” which is broken at the time of writing.
import React, { Component } from "react"; import jsQR from "jsqr"; import $ from "jquery"; class QrCodeScanner extends Component { constructor(props) { super(props); this.videoRef = React.createRef(); this.state = { qrcode: "", videoError: false } } componentDidMount() { this.checkCameraPermissions(); } componentWillUnmount() { this.stopScanner(); } checkCameraPermissions = async () => { var thisController = this; cordova.plugins.permissions.requestPermission( cordova.plugins.permissions.CAMERA, function (status) { if (status.hasPermission) { console.log("Camera permission granted"); thisController.startScanner(); } else { console.log("Camera permission denied"); thisController.state.videoError = true; thisController.setState(thisController.state); } }, function () { console.log("Error requesting camera permission"); thisController.state.videoError = true; thisController.setState(thisController.state); } ); }; startScanner = () => { navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }) .then((stream) => { this.videoRef.current.srcObject = stream; this.videoRef.current.play(); this.videoRef.current.addEventListener("loadedmetadata", this.scanFrame); }) .catch((error) => { console.error("Error starting scanner: ", error); this.state.videoError = true; }); }; stopScanner = () => { const stream = this.videoRef.current.srcObject; if (stream) { const tracks = stream.getTracks(); tracks.forEach((track) => { track.stop(); }); } document.getElementById("qrScannerPreview").pause(); }; scanFrame = () => { var thisController = this; const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); const video = this.videoRef.current; canvas.width = video.videoWidth; canvas.height = video.videoHeight; context.drawImage(video, 0, 0, canvas.width, canvas.height); const imageData = context.getImageData(0, 0, canvas.width, canvas.height); const code = jsQR(imageData.data, imageData.width, imageData.height); if (code) { console.log("QR code detected: ", code.data); //Do something with the extracted code. return; } } requestAnimationFrame(this.scanFrame); }; render() { return ( <div style={{ height: "90vh", marginTop: "7vh" }} > <div id="view-qrscanner" > <div> <div className="container-qr"> <div style={{ paddingTop: "1vh" }} > <div align="center"> <h3 style={{ fontWeight: 'bold', fontSize: "1.28rem", color: 'white' }}>Scan your onboarding QR code</h3> <label style={{ padding: "10vw", fontSize: "0.92rem", color: 'white' }}>Postion the QR Code a few inches away</label> </div> <div id="camera" className="pre_capture_frame" style={{ width: '95vw' }} /> {!this.state.videoError && <video style={{ width: "85vw", height: "85vw", margin: '4.5vw', borderRadius: '12px' }} ref={this.videoRef} id="qrScannerPreview" />} {this.state.videoError && <div>Could not start the video source. Please ensure that you have granted camera permissions and that the camera is not being used by another app.</div>} <br /> <div id="tick" align="center" style={{ display: 'none', color: '#94bde9', fontSize: '108px', width: '95vw' }}> ✔ </div> </div> </div> </div> </div> </div> ); } } export default QrCodeScanner;

Sreekumar (KJ) has been a hobby programmer from school days. Codemarvels is his personal blog from the year 2010, where he writes about technology, philosophy, society and a bit about physics.
He now runs a conversational AI company – DheeYantra – focusing his efforts to help businesses improve operational efficiency using digital employees powered by AI.
Leave a Reply