Barcode scanner in React
Today we will show you how to implement a barcode scanner in React. In this example, we will use the quaggaJS in the ReactJS component.
What is QuaggaJS?
QuaggaJS is a barcode-scanner entirely written in JavaScript supporting real- time localization and decoding of various types of barcodes such as EAN, CODE 128, CODE 39, EAN 8, UPC-A, UPC-C, I2of5, 2of5, CODE 93 and CODABAR.
Checkout more articles on ReactJS
Demo Application
Steps to implement barcode scanner in React
- Create a react application
- Install quaggaJS package
- Add scanner functionality in react component
- Output
1. Create a react application
First of all, create a simple react application using the create-react-app
. Run the following command to create an app.
1 | npx create-react-app react-barcode-scanner |
2. Install quaggaJS package
Run the following command to install quaggaJS to implement a barcode scanner.
1 | npm install quagga |
3. Add scanner functionality in react component
We have to initialize the Quagga JS to start the scanner and attach the function to read the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | const _onDetected = res => { setBarcode(res.codeResult.code); }; const startScanner = () => { Quagga.init( { inputStream: { type: 'LiveStream', target: document.querySelector('#scanner-container'), constraints: { facingMode: 'environment' // or user } }, numOfWorkers: navigator.hardwareConcurrency, locate: true, frequency: 1, debug: { drawBoundingBox: true, showFrequency: true, drawScanline: true, showPattern: true }, multiple: false, locator: { halfSample: false, patchSize: 'large', // x-small, small, medium, large, x-large debug: { showCanvas: false, showPatches: false, showFoundPatches: false, showSkeleton: false, showLabels: false, showPatchLabels: false, showRemainingPatchLabels: false, boxFromPatches: { showTransformed: false, showTransformedBox: false, showBB: false } } }, decoder: { readers: [ 'code_128_reader', 'ean_reader', 'ean_8_reader', 'code_39_reader', 'code_39_vin_reader', 'codabar_reader', 'upc_reader', 'upc_e_reader', 'i2of5_reader', 'i2of5_reader', '2of5_reader', 'code_93_reader' ] } }, err => { if (err) { return console.log(err); } Quagga.start(); } ); Quagga.onDetected(_onDetected); }; |
Use the following function to draw an indicator on the canvas after the process is done.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | Quagga.onProcessed(result => { let drawingCtx = Quagga.canvas.ctx.overlay, drawingCanvas = Quagga.canvas.dom.overlay; if (result) { if (result.boxes) { drawingCtx.clearRect( 0, 0, parseInt(drawingCanvas.getAttribute('width')), parseInt(drawingCanvas.getAttribute('height')) ); result.boxes.filter(box => box !== result.box).forEach(box => { Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: 'green', lineWidth: 2 }); }); } if (result.box) { Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: '#00F', lineWidth: 2 }); } if (result.codeResult && result.codeResult.code) { Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 }); } } }); |
To stop the scanner, use the following code.
1 2 3 4 5 | const stopScanner = () => { Quagga.offProcessed(); Quagga.offDetected(); Quagga.stop(); }; |
At last, we have to add the HTML element to load the barcode scanner and add the CSS to align the indicator.
1 | <div id="scanner-container" /> |
1 2 3 4 5 6 7 8 9 | #scanner-container { position: relative; } .drawingBuffer { position: absolute; left: 0; top: 0; } |
4. Output
Let’s combine all the code together and see how it looks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | import React, { useEffect, useRef, useState } from 'react'; import Quagga from 'quagga'; const App = (props) => { const firstUpdate = useRef(true); const [isStart, setIsStart] = useState(false); const [barcode, setBarcode] = useState(''); useEffect(() => { return () => { if (isStart) stopScanner(); }; }, []); useEffect(() => { if (firstUpdate.current) { firstUpdate.current = false; return; } if (isStart) startScanner(); else stopScanner(); }, [isStart]); const _onDetected = res => { // stopScanner(); setBarcode(res.codeResult.code); }; const startScanner = () => { Quagga.init( { inputStream: { type: 'LiveStream', target: document.querySelector('#scanner-container'), constraints: { facingMode: 'environment' // or user } }, numOfWorkers: navigator.hardwareConcurrency, locate: true, frequency: 1, debug: { drawBoundingBox: true, showFrequency: true, drawScanline: true, showPattern: true }, multiple: false, locator: { halfSample: false, patchSize: 'large', // x-small, small, medium, large, x-large debug: { showCanvas: false, showPatches: false, showFoundPatches: false, showSkeleton: false, showLabels: false, showPatchLabels: false, showRemainingPatchLabels: false, boxFromPatches: { showTransformed: false, showTransformedBox: false, showBB: false } } }, decoder: { readers: [ 'code_128_reader', 'ean_reader', 'ean_8_reader', 'code_39_reader', 'code_39_vin_reader', 'codabar_reader', 'upc_reader', 'upc_e_reader', 'i2of5_reader', 'i2of5_reader', '2of5_reader', 'code_93_reader' ] } }, err => { if (err) { return console.log(err); } Quagga.start(); } ); Quagga.onDetected(_onDetected); Quagga.onProcessed(result => { let drawingCtx = Quagga.canvas.ctx.overlay, drawingCanvas = Quagga.canvas.dom.overlay; if (result) { if (result.boxes) { drawingCtx.clearRect( 0, 0, parseInt(drawingCanvas.getAttribute('width')), parseInt(drawingCanvas.getAttribute('height')) ); result.boxes.filter(box => box !== result.box).forEach(box => { Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: 'green', lineWidth: 2 }); }); } if (result.box) { Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: '#00F', lineWidth: 2 }); } if (result.codeResult && result.codeResult.code) { Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 }); } } }); }; const stopScanner = () => { Quagga.offProcessed(); Quagga.offDetected(); Quagga.stop(); }; return <div> <h3>Barcode scanner in React - <a href="https://www.cluemediator.com/" target="_blank" rel="noopener">Clue Mediator</a></h3> <button onClick={() => setIsStart(prevStart => !prevStart)} style={{ marginBottom: 20 }}>{isStart ? 'Stop' : 'Start'}</button> {isStart && <React.Fragment> <div id="scanner-container" /> <span>Barcode: {barcode}</span> </React.Fragment>} </div> } export default App; |
1 2 3 4 5 6 7 8 9 | #scanner-container { position: relative; } .drawingBuffer { position: absolute; left: 0; top: 0; } |
Run the application and check the output in the browser.
I hope you find this article helpful.
Thank you for reading. Happy Coding..!! 🙂