Hooks
No hooks found in any category.
useBarcodeDetector
sensorsInstallation
npx usehooks-cli@latest add use-barcode-detector
Description
A hook for detecting barcodes in images using the Web Barcode Detection API. Supports various barcode formats including QR codes, Code 128, EAN, and more.
Parameters
Name | Type | Default | Description |
---|---|---|---|
options? | UseBarcodeDetectorOptions | - | Configuration options for barcode detection |
Parameter Properties
options properties:
Name | Type | Description |
---|---|---|
formats? | string[] | Array of barcode formats to detect (defaults to all supported formats) |
Return Type
UseBarcodeDetectorReturn
Property | Type | Description |
---|---|---|
detect | (source: ImageBitmapSource) => Promise<DetectedBarcode[]> | Detect barcodes in the provided image source |
isSupported | boolean | Whether the Barcode Detection API is supported |
supportedFormats | string[] | Array of supported barcode formats |
isDetecting | boolean | Whether detection is currently in progress |
error | string | null | Error message if detection failed |
Examples
Basic Barcode Detection
Detect barcodes from an image file input
1import { useBarcodeDetector } from '@usehooks/use-barcode-detector';
2import { useRef } from 'react';
3
4function BarcodeScanner() {
5 const { detect, isSupported, isDetecting, error } = useBarcodeDetector();
6 const fileInputRef = useRef<HTMLInputElement>(null);
7
8 const handleFileSelect = async (event: React.ChangeEvent<HTMLInputElement>) => {
9 const file = event.target.files?.[0];
10 if (!file) return;
11
12 try {
13 const barcodes = await detect(file);
14 console.log('Detected barcodes:', barcodes);
15 barcodes.forEach(barcode => {
16 console.log(`Format: ${barcode.format}, Value: ${barcode.rawValue}`);
17 });
18 } catch (err) {
19 console.error('Detection failed:', err);
20 }
21 };
22
23 if (!isSupported) {
24 return <div>Barcode detection not supported</div>;
25 }
26
27 return (
28 <div>
29 <input
30 ref={fileInputRef}
31 type="file"
32 accept="image/*"
33 onChange={handleFileSelect}
34 disabled={isDetecting}
35 />
36 {isDetecting && <p>Detecting...</p>}
37 {error && <p>Error: {error}</p>}
38 </div>
39 );
40}
QR Code Detection
Detect only QR codes from camera stream
1import { useBarcodeDetector } from '@usehooks/use-barcode-detector';
2import { useRef, useEffect } from 'react';
3
4function QRScanner() {
5 const { detect, isSupported } = useBarcodeDetector({
6 formats: ['qr_code']
7 });
8 const videoRef = useRef<HTMLVideoElement>(null);
9 const canvasRef = useRef<HTMLCanvasElement>(null);
10
11 useEffect(() => {
12 let stream: MediaStream;
13
14 const startCamera = async () => {
15 try {
16 stream = await navigator.mediaDevices.getUserMedia({ video: true });
17 if (videoRef.current) {
18 videoRef.current.srcObject = stream;
19 }
20 } catch (err) {
21 console.error('Camera access failed:', err);
22 }
23 };
24
25 startCamera();
26
27 return () => {
28 if (stream) {
29 stream.getTracks().forEach(track => track.stop());
30 }
31 };
32 }, []);
33
34 const scanFrame = async () => {
35 if (!videoRef.current || !canvasRef.current) return;
36
37 const canvas = canvasRef.current;
38 const video = videoRef.current;
39 const ctx = canvas.getContext('2d');
40
41 if (ctx) {
42 canvas.width = video.videoWidth;
43 canvas.height = video.videoHeight;
44 ctx.drawImage(video, 0, 0);
45
46 try {
47 const barcodes = await detect(canvas);
48 if (barcodes.length > 0) {
49 console.log('QR Code detected:', barcodes[0].rawValue);
50 }
51 } catch (err) {
52 console.error('Scan failed:', err);
53 }
54 }
55
56 requestAnimationFrame(scanFrame);
57 };
58
59 if (!isSupported) {
60 return <div>Barcode detection not supported</div>;
61 }
62
63 return (
64 <div>
65 <video ref={videoRef} autoPlay muted onLoadedMetadata={scanFrame} />
66 <canvas ref={canvasRef} style={{ display: 'none' }} />
67 </div>
68 );
69}
Multiple Format Detection
Detect multiple barcode formats with detailed information
1import { useBarcodeDetector } from '@usehooks/use-barcode-detector';
2import { useState } from 'react';
3
4function MultiBarcodeScanner() {
5 const { detect, supportedFormats, isDetecting } = useBarcodeDetector();
6 const [results, setResults] = useState<any[]>([]);
7
8 const handleImageUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
9 const file = event.target.files?.[0];
10 if (!file) return;
11
12 try {
13 const barcodes = await detect(file);
14 setResults(barcodes);
15 } catch (err) {
16 console.error('Detection failed:', err);
17 setResults([]);
18 }
19 };
20
21 return (
22 <div>
23 <div>
24 <h3>Supported Formats:</h3>
25 <ul>
26 {supportedFormats.map(format => (
27 <li key={format}>{format}</li>
28 ))}
29 </ul>
30 </div>
31
32 <input
33 type="file"
34 accept="image/*"
35 onChange={handleImageUpload}
36 disabled={isDetecting}
37 />
38
39 {results.length > 0 && (
40 <div>
41 <h3>Detected Barcodes:</h3>
42 {results.map((barcode, index) => (
43 <div key={index}>
44 <p><strong>Format:</strong> {barcode.format}</p>
45 <p><strong>Value:</strong> {barcode.rawValue}</p>
46 <p><strong>Bounding Box:</strong> {JSON.stringify(barcode.boundingBox)}</p>
47 </div>
48 ))}
49 </div>
50 )}
51 </div>
52 );
53}
Dependencies
react
Notes
- •Only available in browsers that support the Barcode Detection API (Chrome 83+)
- •Requires HTTPS in production environments
- •Supported formats vary by browser and platform
- •Image sources can be HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, ImageBitmap, or File
- •Detection accuracy depends on image quality and barcode visibility
Implementation
1"use client";
2
3import { useState, useCallback, useRef, useEffect } from "react";
4
5interface DetectedBarcode {
6 boundingBox: DOMRectReadOnly;
7 cornerPoints: Array<{ x: number; y: number }>;
8 format: string;
9 rawValue: string;
10}
11
12interface UseBarcodeDetectorOptions {
13 formats?: string[];
14}
15
16interface UseBarcodeDetectorReturn {
17 detect: (source: ImageBitmapSource) => Promise<DetectedBarcode[]>;
18 isSupported: boolean;
19 supportedFormats: string[];
20 isDetecting: boolean;
21 error: string | null;
22}
23
24export const useBarcodeDetector = (
25 options: UseBarcodeDetectorOptions = {}
26): UseBarcodeDetectorReturn => {
27 const [isDetecting, setIsDetecting] = useState(false);
28 const [error, setError] = useState<string | null>(null);
29 const [supportedFormats, setSupportedFormats] = useState<string[]>([]);
30 const detectorRef = useRef<any | null>(null);
31
32 const isSupported =
33 typeof window !== "undefined" && "BarcodeDetector" in window;
34
35 useEffect(() => {
36 if (!isSupported) return;
37
38 const initializeDetector = async () => {
39 try {
40 // Get supported formats
41 const formats = await (
42 window as any
43 ).BarcodeDetector.getSupportedFormats();
44 setSupportedFormats(formats);
45
46 // Create detector with specified formats or all supported formats
47 const detectorFormats = options.formats || formats;
48 detectorRef.current = new (window as any).BarcodeDetector({
49 formats: detectorFormats,
50 });
51 } catch (err) {
52 setError(
53 err instanceof Error
54 ? err.message
55 : "Failed to initialize barcode detector"
56 );
57 }
58 };
59
60 initializeDetector();
61 }, [isSupported, options.formats]);
62
63 const detect = useCallback(
64 async (source: ImageBitmapSource): Promise<DetectedBarcode[]> => {
65 if (!isSupported || !detectorRef.current) {
66 throw new Error("Barcode detection is not supported");
67 }
68
69 setIsDetecting(true);
70 setError(null);
71
72 try {
73 const barcodes = await detectorRef.current.detect(source);
74 return barcodes.map((barcode: any) => ({
75 boundingBox: barcode.boundingBox,
76 cornerPoints: barcode.cornerPoints,
77 format: barcode.format,
78 rawValue: barcode.rawValue,
79 }));
80 } catch (err) {
81 const errorMessage =
82 err instanceof Error ? err.message : "Detection failed";
83 setError(errorMessage);
84 throw new Error(errorMessage);
85 } finally {
86 setIsDetecting(false);
87 }
88 },
89 [isSupported]
90 );
91
92 return {
93 detect,
94 isSupported,
95 supportedFormats,
96 isDetecting,
97 error,
98 };
99};
100
101export default useBarcodeDetector;
102