DEV Community

Yusuf Ginanjar
Yusuf Ginanjar

Posted on

How to Implement QR Scanner in ReactJs

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
Enter fullscreen mode Exit fullscreen mode

or

yarn i qr-scanner
Enter fullscreen mode Exit fullscreen mode

2. Create Component QrReader and write code below

Header

import { useEffect, useRef, useState } from "react";
import "./QrStyles.css";
import QrScanner from "qr-scanner";
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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%);
    }
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)