How to add protected routes (sign up and Login) to react-native using react-navigation 4.0 — part 2

This is part 2 of my “how to add protected routes to react native app” tutorial which will discuss the login and logout code.

We will need to first open our file we created last time named “AuthLoading”, if you remember we created a method called “DetermineScreenNavigation”, we need to make that asynchronous by adding the keyword “async” before the “()” parameters so the method will now look like the below.

DetermineScreenNavigation = async () =>{}

The next thing we need to do is to retrieve an item from asynchronous storage, we will be setting this in the login method in the future. The way to do this is use the “getItem” method of the “AsyncStorage” component like the below. You will need to import the “AsyncStorage” component from “react-native” first though.

const userToken = await AsyncStorage.getItem('userToken');

We then need to add a navigation action which will then use a ternary operator to determine which page to navigate to. So if there is an item in asynchronous storage with the name “userToken” then it knows that a user has already logged in as this token is only created when a user logs in as it is used to validate a user, so it would go to the ‘App’ navigator, whereas, if no token is found it navigates to the default page of the ‘Auth’ navigator which will be the “Login” page.

this.props.navigation.navigate(userToken ? 'App': 'Auth');

You will then need to run the method “DetermineScreenNavigation” within the “componentDidMount” lifecycle method.


So below is now how our “AuthLoading” component should look.

import React from 'react';import {Text,View,StyleSheet,ActivityIndicator, AsyncStorage} from 'react-native';class AuthLoading extends React.Component{componentDidMount(){this.DetermineScreenNavigation()}DetermineScreenNavigation = async () =>{const userToken = await AsyncStorage.getItem('userToken');this.props.navigation.navigate(userToken ? 'App': 'Auth');}render(){return(<ActivityIndicator/>)}}export default AuthLoading;

Now I will move onto our Login.js file changes and paste them below, so please ensure your file now looks like the below, Iwill be explaining the content beneath the code.

import React from 'react';import {Text,View, AsyncStorage, TextInput, TouchableOpacity} from 'react-native';class Login extends React.Component{state = {email:'',password:''}LoginUser = () =>{if('Test' && this.state.password==='123'){AsyncStorage.setItem('userToken','123');this.props.navigation.navigate('App');}}render(){return(<View><View style={{marginTop:50}}><Text>Login page!</Text><View><TextInput placeholder="Enter email" value={} onChangeText={(value)=>this.setState({email:value})}/></View><View><TextInput placeholder="Enter password" value={this.state.password} onChangeText={(value)=>this.setState({password:value})}/></View><View style={{justifyContent:'center'}}><TouchableOpacity onPress={()=>this.LoginUser()}><Text>Login</Text></TouchableOpacity></View></View></View>)}}export default Login;

Ok so from the first line you can see that we imported the TextInput and TouchableOpacity components that is because we will be using 2 text inputs to contain the state values “email” and “password” which will be used for a users login by. I have also created a method called LoginUser which will do a simple if statement to say if email is equal to “Test” and password is equal to “123” then set asynchronous token and navigate to “App” homepage.

However, you obviously would not do this in a real life scenario usually you would send a request to an API endpoint that includes an email and password in the body of the request which then validates this combination in the API against credentials set in the database, and if the credentials are correct then the API will respond successfully with a JWT token specific for that user.

This would then be set in the asynchronous storage which the user will have to retrieve and use as a header when he is sending future requests to the API in order to ensure the request is valid and somewhat secure. I have set the item to “userToken” and given it a value of “123” for now and the user will then be navigated to the “App” stack of the “createSwitchNavigator” which contains our “Other.js” file.

Within our text inputs I have also set the state of both email and password in the “onChangeText” event method and created a Touchable Opacity element to click to run the “LoginUser” method.

Furthermore, I now want to add another property to our “createStackNavigator” and “createAppContainer” components and this is the “initialRouteName” property.

Change your “createAppContainer” and ensure it looks like the below.

export default createAppContainer(createSwitchNavigator({AuthLoading:AuthLoading,App:AppStack,Auth:AuthStack},{initialRouteName:'AuthLoading'}))

Also ensure your “AppStack” looks like the below.

const AppStack = createStackNavigator({Other:Other},{initialRouteName:'Other'});

The “initialRouteName” is basically the first route that loads on the render of the navigator, so the “AuthLoading” component will always be the component that renders first on the app as we are exporting the “createSwitchNavigator” as the default for “App.js” and the “App.js” component will load first, luckily for us this component then dictates whether the user is navigated to the “App” stack navigator or “Auth” stack navigator, depending on whether a token is present in the asynchronous storage.

So when a user logs in the first screen that they will always see is the “Other” screen.

Finally, I will explain how the logout functionality will work, but make changes to your “Other.js” file so it now looks like the below.

import React from 'react';import { Text, View, TouchableOpacity, AsyncStorage } from 'react-native';class Other extends React.Component {LogoutUser = () => {AsyncStorage.removeItem('userToken');this.props.navigation.navigate('Auth');}render() {return (<View><View style={{ marginTop: 50 }}><Text style={{ textAlign: 'center' }}>Other page!</Text><View style={{ alignItems: 'center',marginTop:10 }}><TouchableOpacity onPress={()=>this.LogoutUser()}><Text style={{ textAlign: 'center' }}>Logout</Text></TouchableOpacity></View></View></View >)}}export default Other;

As you can see from the imports I have imported the “TouchableOpacity” component and “AsyncStorage”. I have also created a method named “LogoutUser” which contains an asynchronous storage method named “removeItem” and takes in one parameter which is “userToken” as you remember from before that we set an asynchronous item when we logged in, so when we log out we want to completely remove the item from the storage so the user doesn’t get navigated to the home page after they login but instead are navigated to the sign in page, in addition, I have also navigated the user back to the “Auth” stack.

We can set an initialRouteName for the “Auth” stack too which for our case we will set to be the “Login” component. So when we logout we will be redirected to the “Login” page.

const AuthStack = createStackNavigator({Login: Login,SignUp: SignUp},{initialRouteName:'Login'});

When you first open the app you will see a very basic and ugly login page. Feel free to style this as you wish.

Image for post
Image for post

If you were to enter the email as “Test” and password as 123, you will be directed to the “Other.js” file with a logout button showing, if you were to close the app and reopen it you will see the “Other” page is still showing and not the login, that is because the “AuthLoading” component has found the “usertoken” item, realised you are logged in and directed you to the “App” stack navigator, and since the initial route name of the “App” navigator is “Other” it shows the “Other” component to you, now if you press “Logout” you will be redirected to the Login screen and asynchronous item cleared.

Close the app and reopen it on your simulator and you will see that the Login page shows now because we have cleared the asynchronous storage so the app navigates to the “Auth” stack instead.

Image for post
Image for post

I apologise for the basic styling on the components but I wanted to focus more on the process of logging in/out and staying logged in once the app is closed and go into detail on how react-navigation is magic in how it does this.

Hopefully you learned something from this tutorial and don’t forget to share and clap for this article if you liked it :)

If there is anything I can do to improve then hit me up on Twitter: AlexNotoriousB

Thank you and stay safe!

Software Developer in the UK. With a keen passion for React Native.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store