Navigation is a chapter that has “troubled” RN developers for some time now. Actually, it still troubles us.
When I started with RN, 1.5 years ago, Navigator component was the suggested cross platform approach from React Native documentation itself. The bad news came a few months later, when RN team deprecated it and removed it completely from RN code and documentation. It remains accessible as a deprecated component through this repo, but I wouldn’t suggest going with it, unless you are already experienced with it, know its pros and cons and fits your app purposes exactly.
Unfortunately, RN has not provided a solid solution yet or even a replacement for old Navigator component, thus we are now focusing on community solutions. So if you are about to start a project from scratch, you want to know which navigation library to use and if it will be the right one for you. I want to share my opinion on both; when to use React Navigation package and how to structure your new app as well.
When to use React Navigation
React Navigation is a highly customizable pure JavaScript solution. It’s easy to install and get started and a good choice for apps that are not “heavy” and do not require a lot of resources. If you are new to React Native or your app is not heavy and want to avoid installing and linking a package with native modules, I suggest to try React Navigation.
React Navigation Structures
Let me take a minute here and explain the navigation structuresthat come with React Navigation, meaning the different ways to struct your app’s routing. If you are already familiar with web/mobile navigators, you can skip to next section.
React Navigation offers three structures for routing: the traditional web-like Stack navigator and also the native-like Tab navigator and Drawer navigator.
The stack navigator is the typical solution that most libraries implement. Here, the route objects are saved in a stack, while navigation between screens takes place with the invocation of either a push or a replace method, as shown below. If you use push method, then you can easily go back to the previous view by invoking the pop method. If you replace the stack with a new route object, it means that the application is “done” with the previous screen(s) that were saved in stack and user will not be navigated to them again during this login session. When we use stack navigator there is no specific menu screen or construct (unlike the other navigators). The developer creates his own menu/home screen and the buttons that navigate to other screens.
Tab Navigator implements a type of navigation that exists in native iOS for many years already. Recently, Android added it to its Material design patterns and native components as well (Bottom Navigation View). Tab Navigator is actually a part of the views it navigates to; it occupies a horizontal part of the screen with tabs (sometimes the tabs are not visible in the design — they look like buttons). Tabs/buttons are usually placed at the bottom of the screen but they can also be placed at the top.



Similarly the Drawer Navigator, is an option that originates in mobile native APIs as well. In this case, the menu screen is a separate view that opens and closes with a drawer-like animation. The menu view contains buttons (links) to the application’s screens.



If you are using a Tab Navigator or a Draw Navigator there is a chance that you might want to combine it with one or more Stack Navigators. That can be the case when you navigate to a view and from that view you want to navigate to one or more sub-views that are deeper nested in your app’s logic and have nothing to do with the main tab/drawer.
How to configure your app — introduction to navigation flows
Most apps require authentication in some way in order to access user related data and for that process, applications provide a “separate” set of screens that enable that feature.
From this realization a new concept emerges; one that suggests to have two different navigation flows, one for authentication only and another one for the main app. If the application you are developing has a custom register/login section, then you can utilize and implement this idea as shown below.
Authentication Flow
Custom authentication flow is usually consisted of 2 screens: Register and Login. There is no special requirement here; users simply need to be able to access both screens in order to create a new account and also login. For that purpose, we simply need a Stack Navigator and we configure it in our app’s main file (i.e. index.js/App.js) as shown below:
import { createStackNavigator } from 'react-navigation'// authentication views
import Register from './app/views/Register';
import Login from './app/views/Login';const AuthNavigator = createStackNavigator(
{
Login: { screen: Login },
Register: { screen: Register }
},
{
headerMode: 'none'
}
);
We invoke createStackNavigator methodin order to configure it, which accepts 2 arguments:
- The 1st argument is an object that contains the mapping of the app’s screens, so that the navigator can recognize them. The keys are the names used from the navigator internally to identify the views while the values is an object that consists of the keyword screen as key and the imported view components as values.
- The 2nd argument is the configuration object. It is optional and passed only if we want to override the default configuration. In this case we pass
headerMode: 'none'
in order to remove the default header component passed from the react-navigation library that looks like that:



Main Application Flow
Main application will make use of one or more of the Navigator structs analyzed before. Let’s see a configuration example of a Drawer Navigator which is combined with Stack Navigators in the cases that there are sub-views besides the main views, as explained before. Our App.js file looks like that
// packages
import { createDrawerNavigator, createStackNavigator } from 'react-navigation';// views
import Menu from './app/views/Menu';
import Home from './app/views/Home';
import HomeItemDetails from './app/views/HomeItemDetails';
import Calendar from './app/views/Calendar';
import EventDetails from './app/views/EventDetails';
import Profile from './app/views/Profile';// create the navigators
const HomeStackNavigator = createStackNavigator({
Home: { screen: Home },
HomeItemDetails: { screen: HomeItemDetails }
});const CalendarStackNavigator = createStackNavigator({
Calendar: { screen: Calendar },
EventDetails: { screen: EventDetails }
});// create and configure drawer parent navigator for main app
const AppNavigator = createDrawerNavigator({
Home: { screen: HomeStackNavigator },
Calendar: { screen: CalendarStackNavigator },
Profile: { screen: Profile },
}, {
contentComponent: Menu,
drawerWidth: widthPercentageToDP('100%'),
initialRouteName: 'Calendar'
});
In this example we configure a Drawer Navigator again by passing 2 arguments; the first one configures the navigation while the latter one configures options of the drawer navigator itself.
Starting with the first object, we see that the Drawer Navigator has 3 views to navigate to: Home, Calendar and Profile. Profile is the simplest one because it only navigates to one main view. Home and Calendar both navigate to a main view from which the app can navigate to sub-views, thus we set a stack navigator for each of them.
Finally we configure Menu view, as the one to be shown when Drawer Navigator is opened and Calendar view as the first to be shown when app is opened and after the user has logged in. Lastly, we set the width of the drawer view to be the 100% of the screen.
Combine the 2 flows
Now we need to provide an overall setup for the 2 flows to work together. Our App.js file looks like that:
import { createSwitchNavigator } from 'react-navigation';// create switch navigation with authentication flow and main app
const SwitchNavigator = createSwitchNavigator(
{
Login: AuthNavigator,
App: AppNavigator
},
{
initialRouteName: 'Login'
}
);const App = () => (
<SwitchNavigator />
);export default App;
What do we see here?
We import and invoke the createSwitchNavigator module
2. On invocation we provide 2 configuration objects: the former contains the flows’ mapping, while the latter indicates the starting flow of the total app’s navigation flow.
How to actually navigate through views
React Navigation passes a prop called navigation in every view. This prop is an object that carries the available navigation methods with it. The most common methods we need to use are the following:
- push: used with Stack Navigator only and pushes the new route object into the stack. It can be attached to a button click and navigates to a new view from which we can go back. I.e:
this.props.navigation.push('Profile');
- pop: used with Stack Navigator only and and pops the last route object from the stack. It is automatically attached to the default header that React Navigation adds but if we remove it, like we did before, we need to attach it to a custom back button of our own. We also need to attach it to Android Back Button functionality. I. e.
this.props.navigation.pop();
- replace: used with Stack Navigator only and replaces the whole stack with the new object. It is attached to a button click, exactly as the push method but there is no going back here. I.e.
this.props.navigation.replace('Home');
- openDrawer: used with Drawer Navigator only and opens the menu screen that is configured for this purpose. It is attached to the button that opens the menu screen. I.e.
this.props.navigation.openDrawer();
- navigate: used with all navigator types and navigates to the screen instructed. For the stack navigator it works similarly as the push method, but as pointed out by Luís Mestre in the comment section, it’s not exactly the same. In example, if you navigate to a screen that is already present in the stack, the navigate method will not add it again in the stack, but instead it will pop all the screens saved in the stack on top of it, until it reaches the one to navigate. For the drawer/tab navigators, it simply takes the user to the next view and stack object is not relevant.
this.props.navigation.navigate('Profile')
- goBack: used with Stack Navigator only and has exactly the same functionality as pop method. I.e.
this.props.navigation.goBack();
In case you want to see the complete list of methods and other possible capabilities over the navigation prop have a look at the respective documentation link.
What do you think?
What do you think about this article? What is your library of choice when it comes to React Native? Offer your perspective and ideas in the comments section below.