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. So how do we use and implement it into our application? Here, let's go and try this feature! 🤓
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
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.
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.
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
🧭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:
createSwitchNavigator(RouteConfigs, SwitchNavigatorConfig);
and lets implement that method. Create a new file MainNavigator.js for the navigator. I usually put it inside ./navigators/
directory.
//**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.
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.
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).
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:
render() {
return (
<ApplicationProvider>
<FooContext.Provider value={this.state}>
<RoutedApp />
</FooContext.Provider>
</ApplicationProvider>
);
}
It's done! you created your switch navigator.
🔍Getting Deeper
So, how to create the others? Stack Navigator and TabNavigator? It is the same, lets see from the docs, and what method did they use.
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):
//**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, while in tab navigator they have different options, you can check here.
And please note, that they have defaultNavigationOptions
too that is written inside the NavigatorConfig (the second parameter).
//**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',
},
},
});
📲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:
The blue box is the navigator component, while the green box is your screen component.
And the code, will be somewhat like this:
//**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)
✨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.
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)!
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 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.
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
🎉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☕😉.
Click me to view my full navigator code (Github gist).
Top comments (0)