How to Implement QR Scanner in ReactJs
Published: 2024-05-17 16:24:36

Imagine a QR code as a fancy barcode that holds information like website addresses or secret messages. When you scan a QR code with your phone or a scanner app, it's like using a special translator. The scanner app reads the squiggles and lines of the QR code and turns them back into regular words and numbers that your phone can understand.

Here's a step-by-step breakdown:

1. Secret message in a picture: Information gets squeezed into a special picture called a QR code.
2. Scanning with your camera: You point your phone's camera at the QR code, like taking a picture.
3. Translating the squiggles: A scanner app on your phone reads the lines and squares of the QR code.
4. Getting the message: The app figures out what information is hidden in the QR code.
5. Taking action: Your React app receives the information and does something cool with it, like showing a website or logging you into something.

**In this tutorial, we'll walk you through building a QR code scanner using ReactJS.**

## 1. Install qr-scanner
```
npm i qr-scanner
```
or 

```
yarn i qr-scanner
```

## 2. Create Component QrReader and write code below
Header
```
import { useEffect, useRef, useState } from "react";
import "./QrStyles.css";
import QrScanner from "qr-scanner";
```
Component

```
const QrReader = () => {
	// QR States
	const scanner = useRef<QrScanner>();
	const videoEl = useRef<HTMLVideoElement>(null);
	const qrBoxEl = useRef<HTMLDivElement>(null);
	const [qrOn, setQrOn] = useState<boolean>(true);

	// Result
	const [scannedResult, setScannedResult] = useState<string | undefined>("");

	// Success
	const onScanSuccess = (result: QrScanner.ScanResult) => {
		// 🖨 Print the "result" to browser console.
		console.log(result);
		// ✅ Handle success.
		// 😎 You can do whatever you want with the scanned result.
		setScannedResult(result?.data);
	};

	// Fail
	const onScanFail = (err: string | Error) => {
		// 🖨 Print the "err" to browser console.
		console.log(err);
	};

	useEffect(() => {
		if (videoEl?.current && !scanner.current) {
			// 👉 Instantiate the QR Scanner
			scanner.current = new QrScanner(videoEl?.current, onScanSuccess, {
				onDecodeError: onScanFail,
				// 📷 This is the camera facing mode. In mobile devices, "environment" means back camera and "user" means front camera.
				preferredCamera: "environment",
				// 🖼 This will help us position our "QrFrame.svg" so that user can only scan when qr code is put in between our QrFrame.svg.
				highlightScanRegion: true,
				// 🔥 This will produce a yellow (default color) outline around the qr code that we scan, showing a proof that our qr-scanner is scanning that qr code.
				highlightCodeOutline: true,
				// 📦 A custom div which will pair with "highlightScanRegion" option above 👆. This gives us full control over our scan region.
				overlay: qrBoxEl?.current || undefined,
			});

			// 🚀 Start QR Scanner
			scanner?.current
				?.start()
				.then(() => setQrOn(true))
				.catch((err) => {
					if (err) setQrOn(false);
				});
		}

		// 🧹 Clean up on unmount.
		// 🚨 This removes the QR Scanner from rendering and using camera when it is closed or removed from the UI.
		return () => {
			if (!videoEl?.current) {
				scanner?.current?.stop();
			}
		};
	}, []);

	// ❌ If "camera" is not allowed in browser permissions, show an alert.
	useEffect(() => {
		if (!qrOn)
			alert(
				"Camera is blocked or not accessible. Please allow camera in your browser permissions and Reload."
			);
	}, [qrOn]);

	return (
		<div className="qr-reader">
			{/* QR */}
			<video ref={videoEl}></video>
			<div ref={qrBoxEl} className="qr-box">
				{!videoEl?.current && (
					<img
						src="/static/images/icons/scan_qr1.svg"
						alt="Qr Frame"
						width={256}
						height={256}
						className="qr-frame"
					/>
				)}
			</div>

			{/* Show Data Result if scan is success */}
			{scannedResult && (
				<p
					style={{
						position: "absolute",
						top: 0,
						left: 0,
						zIndex: 99999,
						color: "white",
					}}>
					Scanned Result: {scannedResult}
				</p>
			)}
		</div>
	);
};

export default QrReader;
```
Style: Create QrStyles.css on the same folder

```
.qr-reader {
    width: 430px;
    height: 430px;
    margin: 0 auto;
    position: relative;
}

.qr-reader video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.qr-reader .qr-box {
    width: 100% !important;
    left: 0 !important;
}

.qr-box.scan-region-highlight {
    height: 0px !important;
}

.qr-reader .qr-frame {
    position: absolute;
    fill: none;
    left: 50%;
    top: 50%;
    transform: translateX(-50%) translateY(0);
}

/* Media Queries for mobile screens */
@media (max-width: 426px) {
    .qr-reader {
        width: 100%;
        height: 76vw;
    }

    .qr-reader .qr-frame {
        transform: translateX(-50%) translateY(-10%);
    }
}
```


Congratulations! You've built a basic QR code scanner using ReactJS. This is a powerful tool that you can integrate into your React applications to enable features like attendance tracking, product verification, or even hidden message decoding in games. With some additional development, you can customize the scanner's appearance, handle different scan results, and integrate it seamlessly into your React projects. 

_This article was created with the assistance of Gemini._