Simple QR Code Reader in SolidJS

janu lius
Ralali Tech Stories
4 min readAug 22, 2022

This post is for those interested in implementing a QR Code scanner into your app using Solid as the front end. This tutorial creates a QR Code scanner without using the npm package.

Create solid project

To run Solid, make sure you have Node.js installed. Then, run one of these commands.

npx degit solidjs/templates/js simple-solid-qr-reader
cd simple-solid-qr-reader
npm install
npm run dev

If you get an error like this

Change Node.js version to v16.0.0 or v14.18.0. node: import support added in v16.0.0, v14.18.0. Check here.

After successfully installed, open it using your favorite editor. It will look like this:

Create a component

Create a QrReader.jsx File and add a <video/> tag with an id and other attributes in the src folder with the following:

function QrReader() {
return (
<video id="video" width="640" height="480" autoplay></video>
)
}

export default QrReader

Next, we will select the video element from the component we just created and check if there is a camera available that we can use to stream:

import { onMount } from 'solid-js'

let videoEl = null

function QrReader() {
onMount(() => {
videoEl = document.querySelector('#video')
if (navigator.mediaDevices?.getUserMedia) {
const constraints = {
video: true,
audio: false
}
navigator.mediaDevices.getUserMedia(constraints).then(stream => videoEl.srcObject = stream);
}
});

return (
<video id="video" width="640" height="480" autoplay></video>
)
}

export default QrReader

Add Qr Reader component to src/App.jsx

import styles from './App.module.css'
import QrReader from './QrReader'

function App() {
return (
<div class={styles.App}>
<h1>QR Code Scanner</h1>
<QrReader />
</div>
)
}

export default App

Now, if you open the browser, you will see a live video stream that we can use to scan QR codes.

Barcode scanner functionality

Next, we will use BarcodeDetector, the interface of the Barcode Detection API. First, create a new BarcodeDetector class. Now we have BarcodeDetector class for making the barcode detector function. To start detecting barcodes we use the BarcodeDetector.detect() and run detect code function every 500 milliseconds.

For more detail about BarcodeDetector, check here.

Now src/QrReader.jsx is like this:

import { onMount, onCleanup } from 'solid-js'

let videoEl = null

function QrReader() {
const barcodeDetector = new BarcodeDetector({ formats: ['qr_code'] })

const detectCode = () => {
if (videoEl?.srcObject) {
barcodeDetector.detect(videoEl).then(codes => {
if (codes.length === 0) return

for (const barcode of codes) {
alert(barcode.rawValue)
}
}).catch(err => {
console.error(err)
})
}
}

onMount(() => {
videoEl = document.querySelector('#video')

if (navigator.mediaDevices?.getUserMedia) {
const constraints = {
video: true,
audio: false
}

navigator.mediaDevices.getUserMedia(constraints).then(stream => videoEl.srcObject = stream)
}
})

const timer = setInterval(detectCode, 500)
onCleanup(() => clearInterval(timer))

return (
<video id="video" width="640" height="480" autoplay></video>
)
}

export default QrReader

Additional

Now, if we want to display recently scanned, then there are two files to be improved.

  • src/QrReader.jsx
  • src/App.jsx

First, in the src/App.jsx file, add the detect prop used to get the value of the scanned QR, and then save the scanned deal into the state.

import styles from './App.module.css'
import QrReader from './QrReader'
import { createSignal, For } from 'solid-js'

function App() {
const [recentlyScanned, setRecentlyScanned] = createSignal([])

return (
<div class={styles.App}>
<h1>QR Code Scanner</h1>
<div class={styles.QrReaderWrapper}>
<QrReader onDetect={
(barcode) => {
if (barcode) {
setRecentlyScanned((recentlyScanned) => [...recentlyScanned, barcode.rawValue])
}
}}
/>
<div>
<h2>Recently Scanned</h2>
<ul>
<For each={recentlyScanned()}>
{(scanValue) => {
return (
<li>
{scanValue}
</li>
)
}}
</For>
</ul>
</div>
</div>
</div>
)
}

export default App

Add the code below in the src/App.module.css file.

...
.QrReaderWrapper {
display: flex;
column-gap: 1rem;
}

Finally, change the code below in the src/QrReader.jsx file.

...
function QrReader(props) {
...
const detectCode = () => {
if (videoEl?.srcObject) {
barcodeDetector.detect(videoEl).then(codes => {
if (codes.length === 0) return

for (const barcode of codes) {
props.onDetect(barcode)
}
}).catch(err => {
console.error(err)
})
}
}
...

Now you will see recently scanned in your browser.

Source code

You can find the source code for this tutorial on Github: https://github.com/janulius/simple-solid-qr-reader.

Reference

My name is Janulius. I am a Frontend Engineer at ralali.com. If this post is helpful, please recommend and share it! Thanks for your time.

--

--