Generate a QR for a modern look and feel

Draft Disclaimer: Please note that this article is currently in draft form and may undergo revisions before final publication. The content, including information, opinions, and recommendations, is subject to change and may not represent the final version. We appreciate your understanding and patience as we work to refine and improve the quality of this article. Your feedback is valuable in shaping the final release.

Language Mismatch Disclaimer: Please be aware that the language of this article may not match the language settings of your browser or device.
Do you want to read articles in English instead ?

tags: vuejs, react, qrcode, javascript

Summary

I've met some people saying weird stuff about QR code like:

"saving a QR code in a database"

or

"it is safe 4to save data in a QR code"

I'm bringing some light on this topic. After this, you should have a better understanding of what a QR code is and be able to generate & scan QR code right in the browser with only two libraries

  • What is a QR Code ?
  • How to write a QR code ?
  • How to read a QR code ?
  • Implementation
    • VueJS version
    • React version

What is a QR Code ?

Simply put, it is an image containing data that can be a URL, a contact card or any random text. In other words, a QR code is an encoded version of data.

Keep in mind that encode is not encrypted. Which means everybody can see what information you put in a QR code.

How to write a QR code ?

It is about decoding data from an image.

yarn add qrcode # (or npm i -S qrcode)

How to read a QR code ?

It is about encoding data to an image in some way.

yarn add qrcode-decoder # (or npm i -S qrcode-decoder)

Vanilla javascript implementation

/**
 * @param {object} options
 * @param {string} [options.previewSelector]
 * @param {string} [options.onDecode]
 */
export const qrCodeDecoder = (options) => {
  const stop = () => {
    const video = this.$el.querySelector(options.previewSelector)
    const stream = video.srcObject
    if (stream) {
      const tracks = stream.getTracks()
      for (let i = 0; i < tracks.length; i++) {
        const track = tracks[i]
        track.stop()
      }
    }
    video.srcObject = null
  }
  const start = async () => {
    const qr = new QrcodeDecoder();
    if (!qr.isCanvasSupported()) {
      console.log("Your browser doesn't match the required specs.");
      throw new Error("Canvas and getUserMedia are required");
    }
    const onSuccess = async (stream) => {
      const video = this.$el.querySelector(options.previewSelector)
      video.srcObject = stream
      video.addEventListener('loadedmetadata', () => {
        video.play()
      })
      const result = await qr.decodeFromCamera(video);
      const orderUuid = result?.data
      options.onDecode(orderUuid)
    }
    const onFailure = (error) => {
      console.error(error)
      toast({
        type: 'error',
        title: 'Permission error',
        message: 'App needs to access your webcam to scan QR code'
      })
    }
    navigator.mediaDevices.getUserMedia({
      video: true,
      audio: false
    })
        .then(onSuccess)
        .catch(onFailure)
  }
  return {
    stop,
    start
  }
}

VueJS version

<template lang="pug">
  .qr-code
    video.order_qr-code__preview#order_qr-code__preview
    #result
    .form-actions
      button.button(@click="start") Start
      button.button(@click="stop") Stop
</template>

<script>
  import QrcodeDecoder from 'qrcode-decoder';
  import toast from '~/toast'
  import sweetConfirm from '~/sweet-confirm'

  export default {
    mounted () {
       const { start, stop } = qrCodeDecoder({
          previewSelector: '#order_qr-code__preview',
          onDecode: async (uuid) => {
            if (uuid && await sweetConfirm({
              text: `Do you want to open order ${uuid}`,
              confirmButtonText: 'Yes, open it'
            })) {
              window.location = `/order/${uuid}`
            }
          }
      })
    } 
  }
</script>


<style lang="scss" scoped>
  .order_qr-code__preview {
    width: 100%;
    height: 400px;
  }

</style>

React version

Wrap up

  1. Browser is the new native.
  2. Abstraction is key to modular code. That's what allow us to use the same function for both React and VueJS
  3. QR Code is a nice to have, makes us feel tech-ish, great for encoding public information