Login Application with React Native
Mobile application development with React Native
Introduction
Now that you have set up your React Native environment, it's time to build our first React Native mobile app. You may recall in Introduction to React, we covered the various ways of writing components in React. Components are items that make up bits and pieces within a website or in this case a mobile application. Components are like Lego building blocks, they can be your header, navigation bar, buttons, and even lines. These work together to produce a fully functioning application.
There are two ways of writing a component. Some developers prefer the use of class-based components while other developers prefer using function-based components. The components use JSX which is like an extension of JavaScript. Below are examples of class-based and function-based components.
// This is how a class-based component will look like import React from "react"; class App extends React.Component { render() { return <Text>My React App</Text>; } } export default App; // This is how the same component can be written in functions import React from "react"; function App (){ return <Text>My React App</Text>; }
The key notable difference between React Native and React is that React Native uses components that are exclusive to React Native and React uses components from HTML. In React, we use <h1> tags to make the first heading. But in React Native we do not have <h1>, instead, we use <Text> to draw text on the screen of our application. The text size can be changed by the styling of the components.
Learning Outcomes
By the end of this article , you will be able to: Understand states and how to use them Create a project with React Native Get user input using component Perform validation steps on the frontend
Step 1: Walkthrough of Project Directory
In the previous quest, we generated a React Native application template. Based on the instructions of the previous quest, your root folder should be named react-login-app. This folder is the folder we created in the previous quest. The subfolder login-app is the folder generated by React Native. You may view all the frontend codes for React Native in this folder.
You may be wondering why would we create a new folder when React Native would do so on our behalf. This is done so by convention and industry practice. In the industry, companies would also add their back-end application (server) to the root folder. This is how teams get to collaborate and work on the project together. However, some companies will choose to keep their front-end (React native) and back-end (server) code separate due to security reasons. As a junior developer to React Native, we would recommend you create your own root directory and generate another folder with React or React Native.
In every JavaScript project, there will always be a package.json file. This file contains all of the dependencies needed to run the project. The dependencies installed can be found inside the node_modules folder. When you upload your repository to a version control software like GitHub, GitHub will ignore folders like node_modules and will only keep the package.json file. When you clone the project again, all you need to do is run npm installin your terminal to reinstall the dependencies.
In the login-app/assets folder, you can place assets like images and audio. This folder will contain your application splash screen, icons and more. Some developers would place static images used throughout the application here as well.
The App.js file is the entry file in the application. In it, you will find the code that is generating the output you see on the Expo Go Application. If you change the text within the <Text> tags, and save the file, you will be able to see the code change here live. By convention, developers will create new folders screens and components in the root folder to place the code responsible for the components within the application (e.g. Header) and the different pages within the application.
In the screenshot shown above, notice that the node_modules and .expo folders are grayed out. These are the folders that would not be uploaded to your version control system like GitHub. If you would like to change the rules on which files and folders to be uploaded onto a version control service, you can open the file “.gitignore” file and set the exclusion and inclusion rules.
Lastly, to start your local development server, do open up your terminal and add the following commands.cd login-app npx expo start
You are now ready to start coding!
Step 2: Code Structure
Now, open the App.js file. In general, this is the broad and simplified syntax of a React Native Component file. import <file name> import {<components>} from <location of components> function <Function Name>{ <More JavaScript Code> return( <JSX> ) } export default <Function Name>
Think of a component as a header, or a custom button. You may reuse the components across any pages you use.
In this quest, we will be using a single page application. This quest is all about the basics. In every framework, it is important for us to learn how we get the user’s input. In this case, we can use the <TextInput/> component that comes with the “react-native” software development kit (SDK).
As such, any components will have to be written within the return() statement. You will get an error if you have written it before, or after the return statement.
Step 3: Custom Images
Imagine we are developing an application for a company. First, we will need to source an image for our application. The image will be used for our application header. The image can be a logo, preferably with the same height and width. Once you have acquired your image, name it Header.jpg and place it in the assets folder.
Next, open the App.js file. We will first add the image and apply some styling to our application. As you develop the mobile application, it is highly recommended that you leave Expo Go open on your mobile application. Sometimes during development, your phone my switch off and it will disconnect from your local development server. Once it do so, any changes will not be reflected onto the device and you will need to reload the application again.
Replace this code with the default code in App.js import { StyleSheet, Image, View } from 'react-native';
export default function App() { return ( <Image source={require('./assets/Header.jpg')} style={styles.image}/> ); }
const styles = StyleSheet.create({ container: { justifyContent:"center", alignItems:"center", marginTop:50 }, image:{ width: 200, height: 200, resizeMode: 'contain' } });
In the code above, we have added the image within the View component. This component is like a wrapper that must wrap all the components within the View tag. It is similar to how a div tag works on HTML. We use the Image component in line 6 of App.js and it is essential to explicitly point to the location of our image. If our image is being loaded locally from the assets folder, we must use the “require()” function to load. React Native will immediate return an error if the path given is invalid.
We also gave our View and Image components styles by using the style attribute. Usually, developers will write the styles of each component nearing the end of the script. In line 11, we declared styles as a constant variable which contains the styling of our components. Within StyleSheet.create(), we will define the stylings for container and image. Bear in mind that we are still writing JavaScript code. Even though the properties of the styles are like CSS rules, they are adapted such that it does not break any JavaScript syntax.
Refer to the example below for the difference. // CSS Rules .container { align-items: "center"; justify-content: “center”; }
// JSX styling container:{ alignItems: "center", justifyContent: "center" }
In the example above, you will notice that the JSX styling is similar to CSS rules but we cannot use the hyphen in CSS as it denotes a subtraction operation in JavaScript. Therefore, the styles and properties are capitalised on the second word, e.g. align-items is alignItems.
At this point, in the Expo Go app on your phone, you should see your header image which you placed earlier in the assets folder, near the top of the screen.
Step 4: Text Inputs
In this step, we will learn how to obtain user information and input. In React and React Native, they are efficient as they keep track of changing variables that are displayed on the screen. Whenever these sets of variables are changed, React and React Native will just need to replace the pixels responsible for displaying those variables. These variables are known as states.
Using states in React Native is the same as using states in React. The code below is how we would create and declare a state in React.import React, {useState} from "react" … const [counter, setCounter] = useState(0)
By convention, whenever you encounter a function with the word “use” in front (e.g. useState, useLayoutEffect, useCallback), those are called hooks which are specialised functions. There are various sets of hooks that come built-in with React and you can also write your own set of hooks.
In the above example, we declare counter and setCounter. These two items are within an array. counter is a read-only variable and to change the value of counter, you must use the setCounter function that was declared with it as well. Below are comparisons of the proper way of changing a value of a state and the improper way of changing a value of a state.
// Correct way setCounter(counter + 1) // increasing counter by 1 // Improper way counter = counter + 1; // it will return an error as counter is a read-only variable.
Now, let us explore further with the TextInput component. This component has a few special attributes we can use. The first one is "placeholder" which is the text shown before any text has been entered by the user. The next attribute is “value” which is the current value stored within the TextInput. We can also use the onChangeText attribute to listen for changes within the text field. In App.js, add the code below to the respective lines without the comments.// before line 1 import React, {useState} from "react" // replace line 2 with this line import { StyleSheet, Image, View, TextInput } from 'react-native'; // after line 4 const [username, setUsername] = useState() const [password, setPassword] = useState() // after line 10 <TextInput placeholder='Username' onChangeText={text => setUsername(text)} value={username} style={styles.input} /> <TextInput placeholder='Password' onChangeText={text => setPassword(text)} value={password} style={styles.input} secureTextEntry={true} /> // add a ',' to the } in line 38 the add this code after line 38 input:{ width: 300, margin: 12, paddingBottom:3, borderBottomWidth: 1, }
At this point, view the 'working code' below to check that you have added the lines of code correctly.
In line 22, the attribute secureTextEntry hides the text that was entered by the user. It is common to use this attribute whenever the user is entering a private string.
Working code
Step 5: Verification
We will now add a button for the user to log in. Add the code below after line 23 of App.js. <Button title="Login" onPress={handleClick} /> //replace line 2 with this import { StyleSheet, Image, View, TextInput, Button } from 'react-native';
Now, we will create a file named db.js within the login-app folder. This file is referenced as a local database to log our user in.
Place the code below within the db.js file.export const users = [ { username: 'admin', password: 'admin' }, { username: 'user', password: 'helloworld' } ]
In the first line of the code snippet, we will export the users and go to App.js to import it. After line 2 of App.js, we will import the users from db.js
Add the following line of code to App.js in their respective lines.// add this after line 2 of App.js import { users } from "./db"; //add this before line 9 const handleClick = () => { const user = users.find(u => u.username === username && u.password === password) if (user) { alert('Login successful') } else { alert('Login failed') } }
To check if you added the code correctly, head to 'working code' at the end of this step.
Now, to understand your code better. Each time the button is pressed (line 35), the handleClick function in line 10 is triggered. Since we imported the users object into this script in line 3, we are able to determine if the user exists with their associated password and username.
Using the find function in line 9, we are able determine for each item in users if the username and password both match the username and password that is stored in our states. If they are a match, we will send a success message. If the username and password that was entered, does not match our database, it will return an error statement.
Working code
The first 15 lines of your App.js should now read like this: