How to add protected routes to react-native using react-navigation V4.0 — Part 1

This is a tutorial explaining how to add protected routes to your react-native app using react-navigation.

One of the main features that you may want in an app you build is the ability for a user to signup, login, logout and stay signed in when the app is closed or if a user switches between apps.

This tutorial will be a guide in how to do that using React-Navigation version 4.0 (Not 5.0 yet as I am still getting my head around how to use the new version and I am more familiar with version 4.0)

The firs thing you will need to do as always is to create a new react native project using the below command, you will need to enter this command in the terminal of your chosen code editor.

react-native init awesomereactnavigation

Once the project has fully been created we will need to install quite a few packages since react-navigation depends on other packages to deliver its full features.

Our first package to install will be “react-navigation” itself, to do this enter the below command.

npm install react-navigation

We will now need to install all of the various other packages required. Use the command below to do this.

npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

I won’t be going into detail about what each of these does for this tutorial.

You will now need to install the Pod dependencies for iOS for these packages. Enter the below command at the root of your project to navigate to the iOS folder and install the missing pod dependencies.

cd ios && pod install

You should see something similar to the below in your terminal.

Now after this has completed enter the command “cd ..” to navigate back to the root of your project.

We now need to make some modifications to a file in our Android project of this app, this file is named “MainActivity.java”. You can edit this file by looking for it in the “android” folder in your react native project.

import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

Above are 3 import statements that you need to add to the top of the “MainActivity.java” file.

We then need to add another method to the same file BELOW the “getMainComponentName” method.

@Override  protected ReactActivityDelegate createReactActivityDelegate() {    return new ReactActivityDelegate(this, getMainComponentName()) {      @Override      protected ReactRootView createRootView() {        return new RNGestureHandlerEnabledRootView(MainActivity.this);      }    };  }

So now your MainActivity.java file should look similar to the below apart from the return message that shows the project name in a string.

Adding these pieces of code enables us to finish the installation of the package “react-native-gesture-handler”.

We will now need to install another package as we will be using a fewstack navigators. A stack navigator provides us a way in which to manage our navigation history and transition between screens in our app. If you use a single stack navigator in your app then it is very similar to how a web browser works as your app will “push” and “pop” screens to and from the navigation stack as users are traversing through the screens.

Enter the below command to install it.

npm install react-navigation-stack

We will now need to create our SignUp, Login and Other components, create a folder in the root of your directory called “components” and create 3 javascript files in them called SignUp.js, Login.js. and Other.js

Populate the SignUp.js file with the below for now.

import React from 'react';import {Text,View} from 'react-native';class SignUp extends React.Component{render(){return(<View><View style={{marginTop:50}}><Text>Sign up page!</Text></View></View>)}}export default SignUp;

Populate the Login.js file with the below for now.

import React from 'react';import {Text,View} from 'react-native';class Login extends React.Component{render(){return(<View><View style={{marginTop:50}}><Text>Login page!</Text></View></View>)}}export default Login;

Populate the file “Other.js” with the below for now.

import React from 'react';import {Text,View} from 'react-native';class Other extends React.Component{render(){return(<View><View style={{marginTop:50}}><Text>Other page!</Text></View></View>)}}export default Other;

We now need to setup our navigation containers, these containers are responsible for managing the app state and linking your top level navigator which in our case is in App.js to the rest of our app.

We will first import “createAppContainer” and “createSwitchNavigator” from the package “react-navigation”.

import { createAppContainer, createSwitchNavigator } from 'react-navigation';

createAppContainer is a function that returns a react component, and in our case that component will be a switch navigator that contains the routes for our navigation. CreateAppContainer can also take in another object separated by a comma after the routes you have set which allows for a lot of customisation including colours and header titles.

The component that is exported from the file “App.js” is the component from which every other component descends from so we are able to navigate to these components by using navigation props.

So for now change the “App” class in App.js to the below code.

class App extends React.Component {render() {return (<View><View><Text>Home screen</Text></View></View>)}}

Our next step is to import the 3 files that we created into our “App.js” file.

import Login from './components/Login';import SignUp from './components/SignUp';import Other from './components/Other';

We will then need to create 2 stack navigators. One for our authentication screens and another for screens that will be able to be shown when a user is authenticated.

Below is the code for the App stack.

const AppStack = createStackNavigator({Other:Other});

We give the object a key of “Other” which has the imported component of “Other” as the value.

Below is the code for the Auth stack.

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

Above are the screens that users can view when they are not logged into the system.

We now need to change the “default export” component from the “App” class and change App.js to export a “createAppContainer” instead. This container will take in a “createSwitchNavigator” as a parameter which itself will contain an object with 3 values that will be equal to our stack navigators we just created.

Currently our “createAppContainer” looks like the below but it is not completely finished.

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

We now need to create a component for the “AuthLoading” key.

Create a new javascript file in the components folder called “AuthLoading.js”, this will contain a loading indicator which will determine whether to go to a default authentication screen or default app screen depending on whether a user token can be found in asynchronous storage. Usually, when a user logs in to a system they ping off a request to an API to determine if their credentials are correct, if they are then the API will return a token and store that in asynchronous storage for future request to the API.

The AuthLoading component will contain a method that searches for a “userToken” item in asynchronous storage, if one is found then it means the user has logged in previously and not logged out so she/he can be brought to the default app screen, however, if a token is not found it means the user has either logged out or never logged in so is redirected to the default authentication screen. For now populate the file “AuthLoading” with the below.

import React from 'react';import {Text,View,StyleSheet,ActivityIndicator} from 'react-native';class AuthLoading extends React.Component{componentDidMount(){}DetermineScreenNavigation = () =>{
}render(){return(<ActivityIndicator/>)}}export default AuthLoading;

Just a quick word on “createSwitchNavigator”.

The primary purpose of this is to only ever show one screen at a time, it resets the routes to their default state value when a user navigates to another screen, in addition, this navigator does not handle back actions which in the case of logging in is what we want as we don’t want a user to be able to logout simply by pressing the back button on their phone. The posh word for the values the “createSwitchNavigator” takes in is a route config object which maps a “route name” to a “route config” which tells the navigator what screen to show for that route.

So if you had the below in your route configs.

{
Profile: Profile
}

You would use

this.props.navigation.navigate('Profile');

To navigate to and show the profile screen.

This concludes the first part of my tutorial, I am thinking of either making it a 2 or 3 part tutorial, depending on how much depth I want to go into.

I hope to get the second part out today, however, my hands need a rest from all this typing haha.

The next part will explain how the app knows which screen to default to when the user opens the app as well as an introduction to how to log a user out of the app.

I hope you learned something from this tutorial as I found learning about this topic quite difficult and cumbersome and hope to help others have an easier learning experience, if there is anything I can do to make my articles better feel free to respond to this article or contact me on Twitter: NotoriousAlexB

Software Developer in the UK. With a keen passion for React Native & C#. Blog — https://cowboycode.co.uk/