Understanding Navigation In React Native
I'll be taking you through React Navigation. Navigation has to do with the nav bars, tab bars and side menu drawers in your mobile application.
At the end of the tutorial, you should have a pretty good knowledge on the various navigators from React Navigation and how to combine these navigators.
Before we begin...
You should check out the React Native documentation on how to get started with React Native and React Navigation.
Initially, React Native made use of Navigator component which was confusing. Fortunately, the React Native community came up with a stand-alone library called react-navigation. which is what we'll be looking into. Let's begin...
Project Setup
Since we are going to be using the react-native CLI
, let's set up our project following these steps:
- create your project using
react-native init app-name
- install
react-navigation
usingnpm install --save react-navigation
- run your project using either
react-native run-ios
orreact-native run-android
You should have your application up and running. The next step is to implement the three built-in navigators from react-navigation
with a brief explanation.
StackNavigator
Stack means a pile of objects and each object can be removed from the top most object i.e Last-in First-out
from your data structure. We can use this to relate to the StackNavigator which simply means adding screens on top of each other like a stack.
Above is a StackNavigator implemented with three components ScreenOne, ScreenTwo, ScreenThree
.
The entry of the application is App.js
which is imported into index.ios.js
index.ios.js
import React, { Component } from 'react';
import {
AppRegistry
} from 'react-native';
import App from './component/stackScreens/App';
AppRegistry.registerComponent('reactNav', () => App);
In the App.js, the StackNavigator is imported. App.js is a stack that has all components needed for your navigation.
App.js
import React from 'react';
import { StackNavigator } from 'react-navigation';
import ScreenOne from './ScreenOne';
import ScreenTwo from './ScreenTwo';
import ScreenThree from './ScreenThree';
const App = StackNavigator({
ScreenOne: { screen: ScreenOne},
ScreenTwo: { screen: ScreenTwo},
ScreenThree: {screen: ScreenThree}
})
export default App;
NB: The keys ScreenOne, ScreenTwo and ScreenThree can be given any name. It's a name which references the component you want to route to.
The object inside StackNavigator
is known as the StackNavigatorConfig
. Let's see our first screen to be rendered looks like.
ScreenOne.js
...
class ScreenOne extends Component {
static navigationOptions = {
title: "Welcome"
}
render() {
const { navigate } = this.props.navigation
return (
<View style={styles.container}>
<TouchableHighlight
onPress={() => navigate("ScreenTwo", {screen: "Screen Two"})}
style={styles.button}>
<Text
style={styles.buttonText}>Screen One </Text>
</TouchableHighlight>
</View>
);
}
};
...
The navigationOptions
takes header options for your screen e.g title: "Welcome"
. In the app demo above, you'll see the Welcome
text in the toolbar. Other header options include headerTitle
, headerStyle
, headerLeft
e.t.c.
In therender()
, you should see this:
const { navigate } = this.props.navigation;
Logging this.props.navigation
, you have:
The navigation object has the following contained in it:
navigate
- specifies the screen to navigate to, also passes params from one component to another.goBack
- specifies the route you want to go back to.state
- keeps track of New and Last State.
These are some of the items in the object I'll be using. Check out this to read more.
In the onPress()
,
onPress={() => navigate("ScreenTwo", {screen: "Screen Two"})}
I specified the screen to navigate to which is ScreenTwo
and I passed a prop screen
with value "Screen Two" to it.
ScreenTwo.js
...
class ScreenTwo extends Component {
static navigationOptions = ({ navigation }) => {
return {
title: `Welcome ${navigation.state.params.screen}`,
}
};
render() {
const { state, navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Text style={styles.titleText}>{state.params.screen}</Text>
<View style={styles.buttonContainer}>
<TouchableHighlight
onPress={() => this.props.navigation.goBack()}
style={[styles.button, {backgroundColor: '#C56EE0'}]}>
<Text style={styles.buttonText}>Go Back</Text>
</TouchableHighlight>
<TouchableHighlight
onPress={() => navigate("ScreenThree", { screen: "Screen Three" })}
style={[styles.button, {backgroundColor: '#8E84FB'}]}>
<Text style={styles.buttonText}>Next</Text>
</TouchableHighlight>
</View>
</View>
);
}
};
...
The navigationOptions
has the props navigation
which contains the params screen
passed from ScreenOne.js
. It's interpolated to the Welcome
string.
You'll also find onPress={() => this.props.navigation.goBack()}
in the Go Back
button. The goBack()
can take in the routeName
you want to navigate to.
Try to complete the navigation for ScreenThree.js
. If you are stuck, here is the complete code on github.
TabNavigator
The TabNavigator is a little bit different from StackNavigator. Here is the App.js which is the entry of the application.
App.js
...
const App = TabNavigator({
ScreenOne: { screen: ScreenOne },
ScreenTwo: { screen: ScreenTwo },
ScreenThree: { screen: ScreenThree }
}, {
tabBarOptions: {
activeTintColor: '#7567B1',
labelStyle: {
fontSize: 16,
fontWeight: '600'
}
}
});
...
Just like we had in the previous Navigator, we have three screens i.e ScreenOne.js
, ScreenTwo.js
, ScreenThree.js
. Here is a code snippet for ScreenOne.
ScreenOne.js
...
class ScreenOne extends Component {
static navigationOptions = {
title: 'Welcome',
tabBarLabel: 'ScreenOne',
tabBarIcon: ({ tintColor }) => (
<Image
source={require('../images/notification-icon.png')}
style={[styles.icon, { tintColor: tintColor }]}
/>
)
}
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<TouchableHighlight
onPress={() => navigate('ScreenTwo')}
style={[styles.button, {backgroundColor: '#7567B1'}]}>
<Text>Go To Screen Two </Text>
</TouchableHighlight>
</View>
);
}
}
...
The navigationOptions have screen options tabBarLabel
and tabBarIcon
to configure both the label and icons in a tab.
You should be able to do the same on both ScreenTwo.js
and ScreenThree.s
. Here is the complete code.
DrawerNavigator
This is almost similar to TabNavigator. I have two screens i.e ScreenOne.js
and ScreenTwo.js
. A code snippet of ScreenOne:
ScreenOne.js
...
class ScreenOne extends Component {
static navigationOptions = {
drawerLabel: 'Screen One',
drawerIcon: ({ tintColor }) => (
<Image
source={require('../images/notification-icon.png')}
style={[styles.icon, { tintColor: tintColor }]}
/>
)
}
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<TouchableHighlight
onPress={() => navigate('DrawerOpen')}
style={[styles.button, {backgroundColor: '#7567B1'}]}>
<Text style={styles.buttonText}> Open Drawer </Text>
</TouchableHighlight>
</View>
);
}
}
...
One of the major difference between this navigator and the rest is DrawerOpen
and DrawerClose
which opens and closes the drawer.
React Navigation libraries
If you have to use React Native Navigation libraries, you should check out this list of amazing libraries for React Native.
Conclusion
It takes a while to get things right the first time. If you are finding it difficult to understand any of the React Native concepts, don't worry. You just have to keep doing it. To read more on React Navigation, see their documentation. Next up, React Native with firebase.
I Have Two Screen, Using This Code After I run I am Getting an empty Screen.
I am run the App in android mobile. no Error But My First screen Cannot Show Why.
Please Help me to solve this.
Very good!
Thank you so much!!
Can the drawer navigator be used for desktop as well ?