Learn React Native: introduction, Navigation, Data Storage, and a Native module
This is part of the series React Native for Beginners and this article is the first installment towards it. It is assumed that you already know React.
The best way to learn anything is by doing it!
As a tech enthusiast, I always try to look for opportunities to learn new tools and tech. So when my brother wanted a native IOS app, it was a perfect opportunity to learn the famous React Native.
While creating the App, I learned about different components such as Navigation, Storing data, Calling APIs, and etc. Each are very important and I will explain each of them. One can create any application using these components.
What we are going to cover?
Create a Native App QR Scanner that scans a QR code, store it in local storage, and at the end make it beautiful. This 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 but …
The output will be something you can show to your colleagues and be proud of it.
The application code is available on GitHub. You can get the application code according to the app version by checking out particular branch. For example, To get the v0.3.0 application code,
git clone https://github.com/drex44/QR-Scanner.git
git checkout v0.3.0
The code has three branches,
- master: code for QR Scanner v1.0.0
- v0.3.0: code for QR Scanner v0.3.0
- v0.4.0: code for QR Scanner v0.4.0
We will design our app in incremental model. We will add new functionality in each iteration. I encourage you to copy the code and then look at it to understand the significance of each line. If you have any doubt then comment below. It will take time but I will surely answer all of your questions.
May the force be with you and let the hacking begin!
Goals: Hello World App, Using a UI library, Testing your App
We can create our react native application using two famouse toolchains. One is expo and another is react-native.
As the official docs says,
The main benefit of using expo toolchain is that they maintain the native module so that we can focus on building our application. Upgrading and maintaining the app is also very easy. But at the same time you have less control over your app than react-native-cli.
So when we want to create applications fast, use expo. Once the application grows large then one can perform eject (similar to CRA eject) and it will be converted to react-native toolchain.
Now let’s get to the coding and create our first application. Run below command to install expo-cli and then create a new project using it. It will ask you to select a template, choose “blank”.
npm install -g expo-cliexpo init qr-scanner
Open your favorite IDE and edit App.js. This is your main entry point in the application. We cannot use HTML elements in the React Native app. We have to use React Native components. Paste the below code in your App.js,
We have just changed the text inside Text component to “Hello World!”. “View” component is the building block in react 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 application. Expo has IOS/Android client application. you will need the expo client to run the application or if you prefer using emulator then you have to setup android studio for android and xcode for IOS. Using expo client is fast and we can get started within minutes so we will use the expo client. Download it on your device and then run below command inside the project root,
Now open your expo client on the mobile device and scan the QR code. Make sure that both your computer and the mobile device are on the same network. if they are not then you can create and login to your expo account in your computer and mobile device to test the application over the internet. Congratulations, you have successfully created and ran a native application.
You can check out the official react native components from the docs and it is also possible to create our own UI components. As the need grew to create better components, various open source packages came forward with the solution. Some of the famous options are Native Base, React Native Elements, Shoutem-UI. We will be using Native Base.
Install Native Base, react-native-easy-grid(for layouts) and vector-icons(for icons),
npm install native-base --save
npm install @expo/vector-icons --save
npm install react-native-easy-grid --save
yarn add native-base --save
yarn add @expo/vector-icons --save
yarn add react-native-easy-grid --save
Now change the App.js with the below code,
For more information, check out Native Base Components.
The code written in componentWillMount() is to load the fonts before the component is rendered. These fonts are used by Native Base internally and it will throw a runtime error if those are not loaded before the component is rendered.
We won’t be using footer and custom header so we will delete them in the next step. I used the default example here to showcase how beautiful app can be created using existing UI libraries.
Just as one can use URL/routes to structure the web application, one has to use different screens in a native application. We basically create different screens and call each screen based on some user input and predefined conditions in the App.js(remember, App.js is single point of entry in our app). We can create our own Navigation mechanism and handle different screens by showing/ hiding different components inside our App.js but we don’t want to reinvent the wheel.
npm install --save react-navigation
Create a new folder named components and a new file named Navigation.js in it. Copy the below code in Navigation.js,
The code is very simple. We create three screens named, Scanner, History, and Result. Screens are nothing but a react component. Here, we have created three components named ScannerScreen,HistoryScreen, and ResultScreen. Then we create a RootStack where we define the names of the screens and assign React components to them. i.e. we have assigned Scanner name to the ScannerScreen component. Then we specify the initial screen to be shown by specifying initialRouteName. Finally, we export the RootStack by wrapping it inside createAppContainer.
This is very important step so don’t forget to wrap your RootStack inside the createAppContainer otherwise you will get an error.
React navigation automatically sets “navigation” object inside the Screen’s props when we create the stack. it is used to perform various navigations inside the screen. For example, here in the ScannerScreen, we have used it to navigate to the other screens, History and Result.
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,
Congratulations, now you know how to handle multiple Screens.
If you’re curious about the navigation bar then it is added by react navigation by default and it can be controlled globally and also locally in each screen. Here we have configured the header bar locally in each component. i.e. In ScannerScreen, we have removed the header completely. In HistoryScreen and ResultScreen, we have assign header titles. For more information, check out configuring the header bar on react navigation official docs.
Fun Fact: Consider a stack navigator with screens A and B. After navigating to A, its
componentDidMountis called. When pushing B, its
componentDidMountis also called, but A remains mounted on the stack and its
componentWillUnmountis therefore not called. When going back from B to A,
componentWillUnmountof B is called, but
componentDidMountof A is not because A remained mounted the whole time. To overcome this, we have to use
lifecycle events provided by react navigation.
Goals: How to store data locally.
Every native application needs to store data such as user status, logged in status, app configuration etc. We can use SecureStore, AsyncStorage, SQLite, and Realm. This are most widely and easy to use services.
Realm is very famous and used widely but you have to perform expo eject to use it so we won’t be discussing it here. But it is useful to know about such tool so you may use it in future.
SecureStore and AsyncStorage both are key-value storage system. The only difference between them is the way they store the data. SecureStore encrypts the data while AsyncStorage stores it in plain text.
We won’t be using SecureStore or AsyncStorage. We will only use SQLite in our application but I have mentioned them here because they are very useful and easy to use.
iOS: Values are stored using the keychain services as
kSecClassGenericPassword. iOS has the additional option of being able to set the value’s
kSecAttrAccessible attribute, which controls when the value is available to be fetched.
we can use below methods to manipulate the data.
- For more information, check out official SecureStore docs.
It has the similar API as SecureStore. we mainly use below methods,
For more methods, please check the official expo docs.
When we want to save large amount of structured data then we can use SQLite. SQLite is local lightweight SQL database.
As mentioned above, An alternative to SQLite: Realm Database is a fast, easy to use, and open source alternative to SQLite and Core Data.
We will create a new Database object from the SQLite and perform some transaction on it.
Create a new file “components/SQL.js” and paste the below code in it,
As the Screen components grow, it will be tough to keep it in the Navigation.js. So let’s separate the Navigation and Screen components. Create a new folder named Screens. Create three files ScannerScreen.js, HistoryScreen.js, and ResultScreen.js. So the Navigation.js will look like this now,
Use the below code for each screen.
Finally, we have to call the InitDatabase method into App.js,
You can add a new row in the database using the input field. Type something and click on ADD TO DB. To check the stored results, check the history screen.