DEV Community

Cover image for Implementing a QR Scanner and send request to backend using next js
Md. Khalid Hossen
Md. Khalid Hossen

Posted on

Implementing a QR Scanner and send request to backend using next js

In this article, I'll walk you through creating a QR scanner in Next.js using the @yudiel/react-qr-scanner library. We'll integrate it with basic functionalities like selecting devices, pausing scans, and customizing tracker overlays.

Why Use @yudiel/react-qr-scanner?

The @yudiel/react-qr-scanner library provides an easy-to-use interface for scanning various barcode and QR code formats. It supports custom overlays and multiple formats, making it versatile for different applications.

Prerequisites

  1. Familiarity with React and Next.js.
  2. A Next.js project setup.
  3. Install the library:
yarn add @yudiel/react-qr-scanner
Enter fullscreen mode Exit fullscreen mode
  1. for local testing scanner you need to enabled below chrome flag:

chrome://flags/#usafely-treat-insecure-origin-as-secure

Note: go to chrome tab and then search usafely-treat-insecure-origin-as-secure and enabled.

Implementation

Here’s the complete code for the scanner page in Next.js.

ScannerPage Component

"use client";

import { useState } from "react";
import {
  Scanner,
  useDevices,
  outline,
  boundingBox,
  centerText,
} from "@yudiel/react-qr-scanner";

const styles = {
  container: {
    width: 400,
    margin: "auto",
  },
  controls: {
    marginBottom: 8,
  },
};

export default function ScannerPage() {
  const [deviceId, setDeviceId] = useState<string | undefined>(undefined);
  const [tracker, setTracker] = useState<string | undefined>("centerText");
  const [pause, setPause] = useState(false);

  const devices = useDevices();

  function getTracker() {
    switch (tracker) {
      case "outline":
        return outline;
      case "boundingBox":
        return boundingBox;
      case "centerText":
        return centerText;
      default:
        return undefined;
    }
  }

  const handleScan = async (data: string) => {
    setPause(true);
    try {
      const response = await fetch(
        `your-api-url?code=${encodeURIComponent(data)}`
      );
      const result = await response.json();

      if (response.ok && result.success) {
        alert("Success! Welcome to the conference.");
      } else {
        alert(result.message);
      }
    } catch (error: unknown) {
      console.log(error);
    } finally {
      setPause(false);
    }
  };

  return (
    <div>
      <div style={styles.controls}>
        <select onChange={(e) => setDeviceId(e.target.value)}>
          <option value={undefined}>Select a device</option>
          {devices.map((device, index) => (
            <option key={index} value={device.deviceId}>
              {device.label}
            </option>
          ))}
        </select>
        <select
          style={{ marginLeft: 5 }}
          onChange={(e) => setTracker(e.target.value)}
        >
          <option value="centerText">Center Text</option>
          <option value="outline">Outline</option>
          <option value="boundingBox">Bounding Box</option>
          <option value={undefined}>No Tracker</option>
        </select>
      </div>
      <Scanner
        formats={[
          "qr_code",
          "micro_qr_code",
          "rm_qr_code",
          "maxi_code",
          "pdf417",
          "aztec",
          "data_matrix",
          "matrix_codes",
          "dx_film_edge",
          "databar",
          "databar_expanded",
          "codabar",
          "code_39",
          "code_93",
          "code_128",
          "ean_8",
          "ean_13",
          "itf",
          "linear_codes",
          "upc_a",
          "upc_e",
        ]}
        constraints={{
          deviceId: deviceId,
        }}
        onScan={(detectedCodes) => {
          handleScan(detectedCodes[0].rawValue);
        }}
        onError={(error) => {
          console.log(`onError: ${error}'`);
        }}
        styles={{ container: { height: "400px", width: "350px" } }}
        components={{
          audio: true,
          onOff: true,
          torch: true,
          zoom: true,
          finder: true,
          tracker: getTracker(),
        }}
        allowMultiple={true}
        scanDelay={2000}
        paused={pause}
      />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Code Explanation

  1. Device Selection: Use useDevices to fetch the list of available video input devices.

  2. Custom Tracker: Provide visual guidance for users with overlays like outline, boundingBox, and centerText.

  3. Scan Handling: Pause the scanner after detecting a QR code, and fetch API data for validation.

  4. Scanner Configuration: Customize scanner formats, overlays, and multiple QR codes handling.

Top comments (0)