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
- Familiarity with React and Next.js.
- A Next.js project setup.
- Install the library:
yarn add @yudiel/react-qr-scanner
- 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>
);
}
Code Explanation
Device Selection: Use useDevices to fetch the list of available video input devices.
Custom Tracker: Provide visual guidance for users with overlays like outline, boundingBox, and centerText.
Scan Handling: Pause the scanner after detecting a QR code, and fetch API data for validation.
Scanner Configuration: Customize scanner formats, overlays, and multiple QR codes handling.
Top comments (0)