Navigation in React Native: From Zero.
Tags: react, reactnative, webdev, beginners
Published: 2020-01-07 14:52:50

You are developing a React Native application, and of course, you must be wanted to make your app with a lot of routes or screens. Of course, when you Googled it, you will find [React Navigation](https://reactnavigation.org). So how do we use and implement it into our application? Here, let's go and try this feature! 🤓
<hr>
##Before We Start
Please note, that I am using Expo for this article, please tell me if you have any problems.

###Setup
If you are using expo-cli, you can run
```
expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context
```
and if you are using bare project, you can use yarn/npm to install the dependencies
```
yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context
```
For bare project, you can see the full instruction [here](https://reactnavigation.org/docs/en/getting-started.html#install-into-an-existing-project)

###The navigators
First, we must know that there are some types of navigation:
- Switch Navigator
- Stack Navigator
- Tab Navigators (and drawer navigators)

And, what are their differences?

####1. Switch Navigator
Switch navigator allows user to switch between screens or route. It will not save your back stack, or navigation history. In real world example, if you have an app with a login screen and a dashboard screen, of course you don't want the user navigates back to login screen from dashboard using back button. The solution is switch navigator, with it, the user can not back into the login screen, instead it will exit the app from the dashboard.
As the name 'switch', the user switches between routes/screen.

<img src="https://i.imgur.com/Xn6xQf2.gif" width="200px" height="350px"/>
<figcaption>Switch Navigator</figcaption>

_See that it closes the app instead back into the home page when I pressed back_

####2. Stack Navigator
Stack navigator is different from switch navigator, but the function is similar, it is allows the user to navigate between screens/routes. The main difference is It will save your back stack/navigation history. You can also add a header to the screen. A header itself, is indeed the top bar of the screen. For example, you have a product list and the detail screen. In this context, you have to implement stack navigator to the screens.

<img src="https://i.imgur.com/FQ0XPIz.gif" width="200px" height="350px"/>
<figcaption>Stack Navigator</figcaption>

####3. Tabs and Drawer Navigators
It is as its name, the tabs and drawer navigators. It saves your back stack, and it will navigate the user with a press on the items. There is some variants that provided by react navigation, such as: BottomTabNavigator, MaterialTopTabNavigator, and others.
_Please note that in this article, I will use BottomTabNavigator_

<img src="https://i.imgur.com/g3MLKyN.gif" width="200px" height="350px"/>
<figcaption>Bottom Tab Navigator</figcaption>
<hr>
##🧭Let's Create Our Navigation!
###Creating the Navigator
React Navigation let you create and customize your navigation, it can be flexible and complex. But first, lets create a simple one!

So, lets say that I have 3 Screens: Splash, Auth, and Application screen. The question is, what are we gonna use? Switch or Stack?
From the context, we have splash and authentication screen. And of course, we don't want to go back to splash screen when we are at the Authentication Screen.
So the answer is indeed __Switch Navigator__.

From the docs, to create a simple switch navigator, we can use this method:
```jsx
createSwitchNavigator(RouteConfigs, SwitchNavigatorConfig);
```
and lets implement that method. Create a new file __MainNavigator.js__ for the navigator. I usually put it inside `./navigators/` directory.
```jsx
//**Other Imports**
import { createSwitchNavigator } from 'react-navigation';
export default const MainNavigator = createSwitchNavigator(
  {
    Splash: { screen: SplashScreen },
    Auth: { screen: AuthScreen },
    Application: { screen: AppScreen },
  },
  {
    initialRouteName: 'Splash',
  }
);
```
On the code above, we create a switch navigator with an object filled with all the 3 screens. In the object, the JSON key is the name of the route (e.g. Splash, Auth, Profile, etc.), it can be anything as it make sense. And the value is the Screen React Component itself (you should import it first).

The second parameter is SwitchNavigatorConfig, and we filled it with an object.
From the code above, the value in the object is initialRouteName, it will configure where should the navigator navigate first when it is fired. In that code, we set it to Splash, so when the MainNavigator fired/mounted, it will open SplashScreen.

There are some config that you can change and modify, like the navigation options, and many more. You can see the list in the [navigator docs](https://reactnavigation.org/docs/en/switch-navigator.html).

<small>_Note: Actually you can simply type `Splash: SplashScreen` in the navigator object, but it will be better to use the above example so that we can insert the `navigationOptions` later._</small>

###Mounting the Navigator into Root Component
So, we have the navigator file, and we created the navigator. How do we fire it or mount it into the application? Of course it won't be fired itself with magic, we will import, and use it inside our App.js (the root component).
```jsx
const RoutedApp = createAppContainer(MainNavigator);
//**Other Imports**

export default class App extends React.Component {
  render() {
    return (
      <RoutedApp />
    );
  }
}
```
Then, try to launch your application. If you are using expo like me, just fire `expo start`. Hopefully, when you launch the application, it will navigate to SplashScreen.
Please note, that if you have some context or provider, you can wrap `<RoutedApp />` with the providers. For example:
```jsx
  render() {
    return (
      <ApplicationProvider>
        <FooContext.Provider value={this.state}>
          <RoutedApp />
        </FooContext.Provider>
      </ApplicationProvider>
    );
  }
```
It's done! you created your switch navigator. 
<hr>
##🔍Getting Deeper 

So, how to create the others? [Stack Navigator](https://reactnavigation.org/docs/en/stack-navigator.html) and [TabNavigator](https://reactnavigation.org/docs/en/bottom-tab-navigator.html)? It is the same, lets see from the docs, and what method did they use.
```jsx
createStackNavigator(RouteConfigs, StackNavigatorConfig);
//And
createBottomTabNavigator(RouteConfigs, TabNavigatorConfig);
```
The difference between them all is the config of the navigator, there are complete list if you explore the navigator docs.

###RouteConfigs
All 3 Navigators that I mentioned above (Switch, stack, tabs/drawer) have RouteConfigs which holds your routes/screen in one JSON object.
Here is a simple example (taken from the [docs](https://reactnavigation.org/docs/en/stack-navigator.html#routeconfigs)): 
```jsx
//**Other Imports**
import { createStackNavigator } from 'react-navigation-stack';

const foo = {
  Profile: {
    screen: ProfileScreen,
    // Optional: When deep linking or using react-navigation in a web app, this path is used:
    path: 'profile/:id',
    // The action and route params are extracted from the path.
    navigationOptions: {
      title: 'My Profile', //The header title (Topbar/actionbar title)
      ...OtherOptions
    }
  },
  ...OtherRoutes //Other routes goes here
}

export default const MyStackNavigator = createStackNavigator(foo);
```
###navigationOptions
Switch and Stack navigator have similar navigationOptions, you can see the list [here](https://reactnavigation.org/docs/en/stack-navigator.html#navigationoptions-for-screens-inside-of-the-navigator), while in tab navigator they have different options, you can check [here](https://reactnavigation.org/docs/en/bottom-tab-navigator.html#navigationoptions-for-screens-inside-of-the-navigator).

And please note, that they have `defaultNavigationOptions` too that is written inside the NavigatorConfig (the second parameter).
```jsx
//**Other Imports**
import { createStackNavigator } from 'react-navigation-stack';

const Foo = createStackNavigator(
  {
    Home: {
      screen: HomeScreen,
      navigationOptions: {
        header: null, //No header in this screen
      },
    },
    Profile: {
      screen: ProfileScreen,
      navigationOptions: {
        title: 'Test Page',
      },
    },
  },
  {
    defaultNavigationOptions: {
      headerStyle: {
        backgroundColor: 'red',
      },
    },
  });
```
<hr>
##📲Creating Full Navigation
After you learn the basics, lets move on to the complex one. 

####The problem
Lets have some problem!
You have an application, and you need some screen/route like this:
- A Loading/Splash Screen
- Authentication Screens (includes Sign In and Registration Screen)
- The Application Screens (Home screen, Profile screen, and Edit profile screen)
The user wants it to be a bottom tabbed application.

In Authentication screen, you can navigate between Sign in and registration screen. In Application Screens, we need a Bottom Tab Navigator to separate the routes inside it.
You can think and have the structure in mind before moving to the solution.

####The solution
So, here we go. Lets distinguish them into 3 groups of screens, the first one is the Splash screen (it is a single screen), the Authentication group, and the Application group. For those groups, we use __Switch Navigator__. Easy.

Onto the next one! 
Splash Screen is a single screen, so let it be. 
The authentication group has 2 screens: Sign In and Registration. So let's create a __Stack Navigator__, call it _authentication stack_. 
And the last one, Application group. We have 3 screens: Home, Profile, and Edit Profile. The user wants to have a bottom tab in their app. So, lets put home and profile screen into bottom tab navigator.
And, we have Edit Profile screen, which will not be on the bottom tab, of course. We will put it alongside the bottom tab navigator (home & profile), and put them into __Application Stack__ (we will use stack navigator for the application group)

Here is the summary: 

<img src="https://i.imgur.com/nrE02mQ.png" alt="nav"/>
The blue box is the navigator component, while the green box is your screen component.

And the code, will be somewhat like this:
```jsx
//**imports here...
const AuthStack = createStackNavigator({
  Login: LoginScreen,
  Register: RegistrationScreen,
});

const TabStack = createBottomTabNavigator({
    Home: HomeScreen,
    Profile: ProfileScreen,
  }
);

const AppStack = createStackNavigator({
    MainTabs: TabStack,
    EditProfile: EditProfileScreen,
  }
);

const MainNavigator = createSwitchNavigator(
  {
    Loading: LoadingScreen,
    App: AppStack,
    Auth: AuthStack,
  },
  {
    initialRouteName: 'Loading',
  }
);
export default MainNavigator;
```
From the code, you can see that you can group some screens into one navigator, and put the navigator itself onto a parent navigator.

The complete code with navigation options will be posted in Github gist. (link down below)
<hr>
##✨Customizing Our Navigators
####Creating Tab Bar Icons and Labels
The default tab bar icon do not have any icons. You should import it from outside libraries. You can just import and use `@expo/vector-icons` if you are using Expo. You can use other libraries too, like eva icons from [@ui-kitten](https://akveo.github.io/react-native-ui-kitten/).

The icon and label itself is a react component, so you can create and customize those easily. Lets customize our tab bar (using expo vector icons)!
```jsx
import { Ionicons } from '@expo/vector-icons';
import { createBottomTabNavigator } from 'react-navigation-tabs';
//**other imports**
const TabStack = createBottomTabNavigator(
  {
    Favorites: {
      screen: FavoritesScreen,
      navigationOptions: {
        /*
          There are 3 parameters passed that you can use,
          focused : boolean => wether the screen is focused/not
          horizontal : boolean => wether phone orientation is landscape/potrait
          tintColor : string
        */
        tabBarIcon: ({ focused, horizontal, tintColor }) => {
          let iconName = `md-heart${focused ? '' : '-empty'}`;
          return <Ionicons name={iconName} size={24} color={tintColor} />;
        },
      },
    },
    ...OtherScreens
  },
  {
    tabBarOptions: {
      showIcon: true,
      showLabel: false,
      activeTintColor: Colors.primary, //You can use hex code too.
      inactiveTintColor: Colors.primary,
    },
  }
//**Other navigators**

```

From the code above, you can see, the icon component is saved under `tabBarIcon` key in navigationOptions of FavoritesScreen. It will changes the icon when the screen is active or not.
The tabBarOptions is the default options for all icons in tab bar, you can change the tint color there. You can see the [docs](https://reactnavigation.org/docs/en/bottom-tab-navigator.htm) for the full feature list.

####Screen Headers
Screen header is the top bar of your app, it can contain back button, the title, and much more.
For example, I can have a stack navigator screen with header or not with header in it. To do this, we are using navigation options of the route, the header options.
```jsx
const AuthStack = createStackNavigator({
  Login: {
    screen: LoginScreen,
    navigationOptions: {
      //The screen will not have any headers.
      //Actually, you can create your own header component and insert it here!
      header: null, 
    },
  },
  Register: {
    screen: RegistrationScreen,
    navigationOptions: {
      title: 'Register', //the screen will have a header with Register title.
      headerStyle: { } //Add some style here! e.g. margin or colors
    },
  },
});
```
*Please note that if you leave the header as default, not null, it will have back button as default. So do not worry about the top left back button*
<hr>
##🎉And, We're Done!
At this point, you can create and customize your own routes for the navigation. Further more, you can use `path` in your route for more advanced feature. Also try to create a custom header or tab bar. Finally, you can learn to add some animations and create a complex custom routes.

That's was it from me. Thank you for you to read this long article 😊. I hope you can learn something from this. And please give me more feedback and suggestion if there is any mistake in the article, I would be glad to fix it.
All content in this article is completely taken from my experience in learning React Native.

And lastly, feel free to [buy me a coffee](buymeacoff.ee/stYpUWh)☕😉.

[Click me](https://gist.github.com/evangunawan/91204639429bf713f02272abc1880765) to view my full navigator code (Github gist).