10.10.2019 Views

3-React Native for beginners - By Dhanraj Acharya

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

While creating the App, I learned about different components such as Navigation, Storing data, Calling APIs, and etc.<br />

Each are very important and I will explain each of them. One can create any application using these components.<br />

What we are going to cover?<br />

Create a <strong>Native</strong> App QR Scanner that scans a QR code, store it in local storage, and at the end make it beautiful. This<br />

is going to be a long tutorial so grab yourself a cup of coffee and sit tight. Roughly, it is going to take about 1:30–2 hour<br />

but …<br />

The output will be something you can show to your colleagues and be proud of it.<br />

Source Code<br />

The application code is available on GitHub. You can get the application code according to the app version by checking<br />

out particular branch. For example, To get the v0.3.0 application code,<br />

git clone https://github.com/drex44/QR-Scanner.git<br />

git checkout v0.3.0<br />

The code has three branches,<br />

master: code <strong>for</strong> QR Scanner v1.0.0<br />

v0.3.0: code <strong>for</strong> QR Scanner v0.3.0<br />

v0.4.0: code <strong>for</strong> QR Scanner v0.4.0<br />

Tutorial<br />

We will design our app in incremental model. We will add new functionality in each iteration. I encourage you to copy<br />

the code and then look at it to understand the significance of each line. If you have any doubt then comment below. It<br />

will take time but I will surely answer all of your questions.<br />

May the <strong>for</strong>ce be with you and let the hacking begin!<br />

v0.1.0<br />

Goals: Hello World App, Using a UI library, Testing your App<br />

We can create our react native application using two famouse toolchains. One is expo and another is react-native.<br />

As the official docs says,<br />

Expo is a free and open source toolchain built around <strong>React</strong> <strong>Native</strong> to help you build native iOS<br />

and Android projects using JavaScript and <strong>React</strong>.<br />

Expo provides a shared native runtime so you don’t write native code, you focus on writing your<br />

<strong>React</strong> app in JavaScript.


If you want to use any native module such as camera, location service etc then you have to use npm module which will<br />

contain some plat<strong>for</strong>m specific native code and then you have to link it. You can even create your own native modules<br />

by writing native code but then it won’t be pure javascript.<br />

The main benefit of using expo toolchain is that they maintain the native module so that we can focus on building our<br />

application. Upgrading and maintaining the app is also very easy. But at the same time you have less control over your<br />

app than react-native-cli.<br />

So when we want to create applications fast, use expo. Once the application grows large then one can per<strong>for</strong>m eject<br />

(similar to CRA eject) and it will be converted to react-native toolchain.<br />

Now let’s get to the coding and create our first application. Run below command to install expo-cli and then create a<br />

new project using it. It will ask you to select a template, choose “blank”.<br />

npm install -g expo-cli<br />

expo init qr-scanner<br />

Open your favorite IDE and edit App.js. This is your main entry point in the application. We cannot use HTML elements<br />

in the <strong>React</strong> <strong>Native</strong> app. We have to use <strong>React</strong> <strong>Native</strong> components. Paste the below code in your App.js,<br />

App.js<br />

App.js<br />

We have just changed the text inside Text component to “Hello World!”. “View” component is the building block in react<br />

native applications. It is used in the same way as a div element is used in the web app. Now it is time to run the<br />

application. Expo has IOS/Android client application. you will need the expo client to run the application or if you prefer<br />

using emulator then you have to setup android studio <strong>for</strong> android and xcode <strong>for</strong> IOS. Using expo client is fast and we<br />

can get started within minutes so we will use the expo client. Download it on your device and then run below command<br />

inside the project root,<br />

npm start<br />

Now open your expo client on the mobile device and scan the QR code. Make sure that both your computer and the<br />

mobile device are on the same network. if they are not then you can create and login to your expo account in your<br />

computer and mobile device to test the application over the internet. Congratulations, you have successfully created<br />

and ran a native application.


Result<br />

v0.1.0<br />

You can check out the official react native components from the docs and it is also possible to create our own UI<br />

components. As the need grew to create better components, various open source packages came <strong>for</strong>ward with the<br />

solution. Some of the famous options are <strong>Native</strong> Base, <strong>React</strong> <strong>Native</strong> Elements, Shoutem-UI. We will be using <strong>Native</strong><br />

Base.<br />

Install <strong>Native</strong> Base, react-native-easy-grid(<strong>for</strong> layouts) and vector-icons(<strong>for</strong> icons),<br />

npm install native-base --save<br />

npm install @expo/vector-icons --save<br />

npm install react-native-easy-grid --save<br />

npm install or yarn add native-base --save<br />

yarn add @expo/vector-icons --save<br />

yarn add react-native-easy-grid --save<br />

yarn<br />

Now change the App.js with the below code,<br />

App.js


App.js<br />

Result<br />

v0.1.1<br />

For more in<strong>for</strong>mation, check out <strong>Native</strong> Base Components.<br />

The code written in componentWillMount() is to load the fonts be<strong>for</strong>e the component is rendered. These fonts are used<br />

by <strong>Native</strong> Base internally and it will throw a runtime error if those are not loaded be<strong>for</strong>e the component is rendered.<br />

We won’t be using footer and custom header so we will delete them in the next step. I used the<br />

default example here to showcase how beautiful app can be created using existing UI libraries.<br />

v0.2.0<br />

Goals: Navigation


Just as one can use URL/routes to structure the web application, one has to use different screens in a native<br />

application. We basically create different screens and call each screen based on some user input and predefined<br />

conditions in the App.js(remember, App.js is single point of entry in our app). We can create our own Navigation<br />

mechanism and handle different screens by showing/ hiding different components inside our App.js but we don’t want to<br />

reinvent the wheel.<br />

We will be using react-navigation which is also suggested on the official docs. So let’s install it.<br />

npm install --save react-navigation<br />

Create a new folder named components and a new file named Navigation.js in it. Copy the below code in Navigation.js,<br />

components/Navigation.js<br />

components/Navigation.js<br />

The code is very simple. We create three screens named, Scanner, History, and Result. Screens are nothing but a react<br />

component. Here, we have created three components named ScannerScreen,HistoryScreen, and ResultScreen. Then<br />

we create a RootStack where we define the names of the screens and assign <strong>React</strong> components to them. i.e. we have<br />

assigned Scanner name to the ScannerScreen component. Then we specify the initial screen to be shown by specifying<br />

initialRouteName. Finally, we export the RootStack by wrapping it inside createAppContainer.<br />

This is very important step so don’t <strong>for</strong>get to wrap your RootStack inside the<br />

createAppContainer otherwise you will get an error.<br />

<strong>React</strong> navigation automatically sets “navigation” object inside the Screen’s props when we create the stack. it is used to<br />

per<strong>for</strong>m various navigations inside the screen. For example, here in the ScannerScreen, we have used it to navigate to<br />

the other screens, History and Result.<br />

Finally, to see our Router in action, we will import it in App.js and use it. This is how it will look after the updates,<br />

App.js


App.js<br />

Congratulations, now you know how to handle multiple Screens.<br />

Result


v0.2.0<br />

If you’re curious about the navigation bar then it is added by react navigation by default and it can be controlled globally<br />

and also locally in each screen. Here we have configured the header bar locally in each component. i.e. In<br />

ScannerScreen, we have removed the header completely. In HistoryScreen and ResultScreen, we have assign header<br />

titles. For more in<strong>for</strong>mation, check out configuring the header bar on react navigation official docs.<br />

Fun Fact: Consider a stack navigator with screens A and B. After navigating to A,<br />

its componentDidMount is called. When pushing B, its componentDidMount is also called, but A<br />

remains mounted on the stack and its componentWillUnmount is there<strong>for</strong>e not called. When<br />

going back from B to A, componentWillUnmount of B is called, but componentDidMountof A is not


ecause A remained mounted the whole time. To overcome this, we have to use lifecycle<br />

events provided by react navigation.<br />

v0.3.0<br />

Goals: How to store data locally.<br />

Every native application needs to store data such as user status, logged in status, app configuration etc. We can<br />

use SecureStore, AsyncStorage, SQLite, and Realm. This are most widely and easy to use services.<br />

Realm is very famous and used widely but you have to per<strong>for</strong>m expo eject to use it so we won’t<br />

be discussing it here. But it is useful to know about such tool so you may use it in future.<br />

SecureStore and AsyncStorage both are key-value storage system. The only difference between them is the way they<br />

store the data. SecureStore encrypts the data while AsyncStorage stores it in plain text.<br />

We won’t be using SecureStore or AsyncStorage. We will only use SQLite in our application but I<br />

have mentioned them here because they are very useful and easy to use.<br />

SecureStore<br />

iOS: Values are stored using the keychain services as kSecClassGenericPassword. iOS has the additional option of<br />

being able to set the value's kSecAttrAccessible attribute, which controls when the value is available to be fetched.<br />

Android: Values are stored in SharedPreferences, encrypted with Android's Keystore system.<br />

we can use below methods to manipulate the data.<br />

SecureStore.getItemAsync(key)<br />

SecureStore.setItemAsync(key,value)<br />

SecureStore.deleteItemAsync(key)<br />

For more in<strong>for</strong>mation, check out official SecureStore docs.<br />

AsyncStorage<br />

It has the similar API as SecureStore. we mainly use below methods,<br />

AsyncStorage.getItem(key)<br />

AsyncStorage.setItem(key, value)<br />

AsyncStorage.removeItem(key)<br />

For more methods, please check the official expo docs.


SQLite<br />

When we want to save large amount of structured data then we can use SQLite. SQLite is local lightweight SQL<br />

database.<br />

As mentioned above, An alternative to SQLite: Realm Database is a fast, easy to use, and open<br />

source alternative to SQLite and Core Data.<br />

We will create a new Database object from the SQLite and per<strong>for</strong>m some transaction on it.<br />

Create a new file “components/SQL.js” and paste the below code in it,<br />

component/SQL.js<br />

As the Screen components grow, it will be tough to keep it in the Navigation.js. So let’s separate the Navigation and<br />

Screen components. Create a new folder named Screens. Create three files ScannerScreen.js, HistoryScreen.js, and<br />

ResultScreen.js. So the Navigation.js will look like this now,<br />

components/Navigation.js<br />

components/Navigation.js<br />

Use the below code <strong>for</strong> each screen.


Screens/ScannerScreen.js<br />

Screens/ScannerScreen.js<br />

Screens/HistoryScreen.js<br />

Screens/HistoryScreen.js<br />

Screens/ResultScreen.js<br />

Screens/ResultScreen.js


Finally, we have to call the InitDatabase method into App.js,<br />

App.js<br />

App.js<br />

You can add a new row in the database using the input field. Type something and click on ADD TO DB. To check the<br />

stored results, check the history screen.<br />

Result


v0.3.0<br />

v0.4.0<br />

Goals: Using the camera/BarCodeScanner modules from expo<br />

When we build a native application, we will most likely use native features. Be<strong>for</strong>e using the native features, we need to<br />

ask <strong>for</strong> the permissions <strong>for</strong> using them. We can do this by using Permission component from expo. We will ask <strong>for</strong><br />

Camera permission. Another module we will use is BarCodeScanner to scan the barcode. It is just a wrapper<br />

over Camera module(You can also use Camera module directly to scan the barcode).


Open ScannerScreen.js and paste the below code. Look at the code and notice that we are checking the permissions in<br />

componentDidMount() method. Once the permission is given, we render the BarCodeScanner in the full screen. We<br />

overlay one History button to check the previous scanned QRs.<br />

Even when the QR code is scanned, it won’t stop the camera and will still try to scan the QRs. So<br />

when another screen will be in focus, still the camera will be active and it will keep scanning the<br />

QRs. To overcome this, we have wrapped our component in withNavigationFocus from reactnavigation.<br />

It gives us a method isFocused in the props to check whether the ScannerScreen is<br />

shown(Focused) on the actual device. We use this prop to conditionally render the<br />

BarCodeScanner component.<br />

Screens/ScannerScreen.js<br />

Screens/ScannerScreen.js<br />

Screens/ResultScreen.js<br />

In ResultScreen component, We just fetch the qr from the navigation parameters and show it in the Text component.<br />

Result<br />

Screens/ResultScreen.js


v0.4.0<br />

Now the application is complete and is functioning but the UI is not very intuitive. So let’s correct it and improve the UI.<br />

v1.0.0<br />

Goal: Better UI<br />

This code is pretty much self explanatory. I am just using style properties and other components to make the UI better. I<br />

am not changing any boilerplate code. So I haven’t written any explanation <strong>for</strong> the code. However, if you have any doubt<br />

then mention it in the comments below, I will answer them.


Create a new file inside components named “commons.js” and paste the below code,<br />

components/commons.js<br />

components/commons.js<br />

Change the code in the below Screens also.<br />

HistoryScreen.js<br />

Screens/HistoryScreen.js<br />

ResultScreen.js


Screens/ResultScreen.js<br />

Screens/ScannerScreen.js<br />

Screens/ScannerScreen.js<br />

Result


v1.0.0<br />

Source code<br />

The application code is available on GitHub.<br />

Homework<br />

It would be a waste of time if you <strong>for</strong>got what you learnt. So here is some homework. Take your time and finish it<br />

yourself. I haven’t provided any code <strong>for</strong> these tasks anywhere. if you face any difficulties then comment and I will<br />

answer them.


P.S. If you found this article helpful, clap!

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!