Embedded QR Code Scanner and Browser in React Native

How to embed a QR Code Scanner and web browser in your next React Native App

Introduction

For a recent freelancing project I was asked to provide QR Code scanning functionality embedded in a stand-alone mobile iOS app. I was aware of QR Code scanning packages available on the node package manager but never really needed to use them in my work! 

Some searching on blogs and packages’ documentation showed you how to read a QR Code and display the information, but not actually DO anything with that information. This was relatively frustrating given that the point of a QR code is to transfer information and usually in the form of a link to a browser. 

In this tutorial, I will take you through show you the steps I took to create an embedded QR Code Scanner for my React Native iOS app. By the end of this tutorial, you will have a good understanding of the parts of React that are relevant to React Native, including state, the lifecycle of a component. 

What you will learn 

  1. The difference between React class components and function components
  2. How to create a React class component
  3. About the React component lifecycle 
  4. How to update the state in a React class component
  5. How to use conditional rendering to toggle between camera and browser in our code. 
  6. About the different React Native built-in core components

Setting up 

I will assume that you are familiar with React Native in setting up a fresh installation. If you are new to React Native then please see here to get set up before continuing with this tutorial!

We must install the following packages 

  1. QR Code Scanner
  2. React Native Web View
  3. React Native Camera

After a fresh installation of React Native, within the app directory in the terminal type the following commands 

npm install --save react-native-camera

npm install --save react-native-webview

npm install --save react-native-qrcode-scanner

Now don’t forget to 

cd ios && pod install

Setting up the QR Code Scanner imports

Before we start, please make sure you’re creating a blind React Native app and using Xcode. This is because we want to be able to allow permission for our app to access the camera which we can do by altering the settings in Xcode.

Let’s first import all the packages 

import React, { Component } from 'react'
import { StyleSheet, View, TouchableOpacity, Text } from 'react-native'
import { WebView } from 'react-native-webview'
import { QRCodeScanner } from 'react-native-qrcode-scanner
import { RNCamera } from 'react-native-camera'
view raw QR.js hosted with ❤ by GitHub

Notes
1. We are importing extending the Component class from React in the first line. This is required to create a React class component.

2. We require some built-in core React Native components. View which is a container that supports layout. Text for displaying text and TouchableOpacity for a button we will create. StyleSheet is necessary to create basic styling choices.

3. We import another React Native component called WebView as a way to display the browser which we can use for our QR Code scanner.

4. We import the QR Code Scanner and RNCamera. RNCamera is what is used by the QR Code scanner package so it’s important to import this as well

As part the setup please do follow the starting instructions for the QR Code Scanner docs here for the QR Code scanner app. You will need to make sure that you allow your app to have permission to access the camera on your phone for the app to work. 

Understanding and Creating the React Class Component

To create this app we are going to use a React class component for our code. This is because class components are useful to modify something called state. You may ask what is state? 

Well, state is an object that we create that can change the values of and this changes how React component renders. If we change the state value, this re-renders the component to provides a change to the output we see on the screen.

An analogy may help us here to cement what this all means. What is the difference between water and ice? The temperature of course! That number is a measurement of thermal energy. Changing that number changes water into ice and vice versa. This is exactly what happens in changing the state of a React Component. The output of the React Component will change depending on a change in the state object. 

We are going to use this concept of state in order to toggle between the QR Code reader and the browser by changing the state object. This is why we want to use a class component!

Class components provide the functionality to change the state object whereas function components are called stateless. This is the fundamental difference between class React components and function React components. Keep this in mind when you’re writing your React and React Native applications. 

With that explanation out of the way Let’s have a look at the first few lines of the code of our App.

export default class App extends Component {
state = {
webview: false,
url: ''
}
}
view raw qr.js hosted with ❤ by GitHub

So to create a React class component we must first extend the React Component. The React component is the simplest building block of React and is necessary to refer to it in any class component we create. 

The state object with two keys webviewand url. We set them to false and '' respectively. The reason we say the key webview is false is that we don’t want the WebView component to render first. Also, we don’t currently yet know what the URL of the QR code is going to be. To direct the WebView component to the correct URL, we need to some be able to how to change that URL when the QR code scans.

@aka_opex — unsplash.com

The QR Code Scanner 

So within the class, we now are ready to go through the code for the QR Code Scanner. 

/*export default class App extends Component {
state = {
webview: false,
url: ''
}
onSuccess = e => {
this.setState({url: e.data, webview: true})
}; */
render() {
return (
<View style={{flex:1}}>
{this.state.webview && (<WebView
source={{uri: this.state.url}}
style={{flex:1}}
scalesPageToFit={true} />
)}
{!this.state.webview && (<QRCodeScanner
onRead={this.onSuccess.bind(this)}
reactivate={true}
reactivateTimeout={4000}/>
)}
)
}
view raw qr.js hosted with ❤ by GitHub

First the render(){} is called. This is the only necessary method for a class component. This is the method that will render our component to do something on a webpage or in our case, the mobile app.

We wrap our logic within a View built-in core component of React Native. This is the equivalent of div HTML tag on rendering. They can be styled, in this case, we are styling the component to fill the full screen using flex:1.

Next, we are providing two pieces of JavaScript within curly braces inside the Viewtag.

We can access the state object key webview by this.state.webview, we know this to be false at this stage. After this expression, you will first notice that the && operator is used. This is because we are using conditional rendering. That is we want to render the component depending on two expressions truthiness or falsiness. It is this that allows us to switch between a browser and the QR code scanner.

The logic goes like this, we defined the state key webviewwith a false value. So with the && operator we get a short-circuiting evaluation of the two subexpressions, that is the whole statement is false.

Now The <WebView> built-in core component is how we tell React Native we want a browser to appear on the screen. The arguments source={{uri: this.state.url}is how we define what URL we want to serve to the browser. We give the component a style and scale it to fit the page.

So in this piece of JavaScript, the expression is false. That is, we don’t want React Native to render the Webview component. That is until we change the webview state. 

In the second piece of JavaScript, we are asking whether the webview variable is false and if the right-hand subexpression is true. The right-hand subexpression returns true, much like any string apart from an empty string gets coerced to true in JavaScript. So the whole expression is true and the QR Code Scanner, therefore, gets rendered.

The QR Code Scanner component has the following arguments. The onread is necessary to provide a way to transfer data when the QR code is read. In this case, we are calling upon a method to be defined, which we are binding that is to allow us to access the method in the class outside the method itself. This is necessary to allow us to use the method as part of the QR Code component.

The reactivate and reactivateTimeout arguments are set accordingly to make sure that the QR code scanner will be able to scan again after the first time it does. We will make use of this in the next section!

So on default rendering of this component, it is the QR code scanner that should appear. 

Now, what is this function we want to be able to do something with when the QR code scanner reads the QR code? 

export default class App extends Component {
/*
state = {
webview: false,
url: ''
}
} */
onSuccess = e => {
this.setState({url: e.data, webview: true})
};
// render() {
.
}
}
view raw qr.js hosted with ❤ by GitHub

Instead of showing the URL on the screen, we want to set the state variable URL to that corresponding URL when the QR code is scanned. 

We do this by calling upon the setState . This allows us to change our state we defined in the constructor method. The setState accepts an object of keys that were defined on the state, but this time we are changing the values of those keys. Firstly we are grabbing the data from the QR code that’s been read, this is bundled in the variable e.dataand setting the URL key to that. We are then changing webview to true.

By using setState the component automatically gets a re-render with the updated state. We are telling React we want to re-render the component. This time the first piece of JavaScript in curly brackets used in our conditional rendering is now true instead of the second piece of JavaScript in curly brackets. The browser now loads with the URL from the QR code!

So with those essentials out of the way, you might be thinking well what is next? Well think about it from a user perspective, we now can browse the website inside our app, but what if we have another QR code we want to scan? We want a way to go back to the QR code scanner. 

Toggling back to QR Code Scanner

So we may have guessed how we toggle back by now. By modifying the state of course! In this case, we want to update the state such that webviewis false. That way the QR code scanner gets rendered instead when we re-render the component.

/*export default class App extends Component {
state = ….
render() {
return (
/*{
<View style={{flex:1}}>
this.state.webview && (<WebView
source={{uri: this.state.url}}
style={{flex:1}}
scalesPageToFit={true} />
)}
{!this.state.webview && (<QRCodeScanner
onRead={this.onSuccess.bind(this)}
reactivate={true}
reactivateTimeout={4000}/>
)}*/
<TouchableOpacity
style={{
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(0,0,0,0.2)',
borderRadius: 50,
width: 75,
height: 75,
position: 'absolute',
right: 5,
bottom: 5
}}
onPress={() => this.setState({ webview: false })}>
<Text style={{textAlign: 'center'}}>Click to Reload</Text>
</TouchableOpacity>
</View>
)
}
view raw qr.js hosted with ❤ by GitHub

Here we provide a button that we can click, with some styling. Essentially we are centring the content by alignItems and justifyContent. We are making the button a circle which has some opacity to it. We have then positioned it absolutely in the bottom right-hand corner of the screen. If you’re familiar with CSS then this should seem pretty familiar to you!

Now with the button, we can use the argument onPress to pass a function or a function call when we press the button. In this case, we’re providing a function that updates the state of webview to false. This then re-renders the React component and this is how we toggle the QR code scanner to appear again. 

The Text built-in component allows us to communicate what the button does, and we make sure that the text is aligned in the centre. 

Now we have a fully functioning QR code scanner with an embedded browser!

If you’d like to see the full code example please see here

Preview

Please see here for a preview of the above code. 

Questions to Check your understanding

  1. What is a React component? 
  2. Why would you use a class component instead of a function component in React Native? 
  3. What is state? 
  4. What is conditional rendering? 

Conclusion

In this tutorial, you have learned the rationale for using class components. We have also covered how using the concepts of state and conditional rendering can be used to dynamically change a screen on your mobile app. In this example, we have shown how you can toggle between a QR code reader and a browser on the same screen, and toggle back to the camera once you’re done browsing! How cool is that? 

Until next time! Please do check out my other articles down below 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s