How To Use Routing with React Navigation in React Native
Table of Contents
Introduction #
React Navigation is a popular library for routing and navigation in a React Native application.
This library helps solve the problem of navigating between multiple screens and sharing data between them.
At the end of this tutorial, you will have a rudimentary social network. It will display the number of connections a user has and provide a way to connect with additional friends. You will use this sample application to explore how to navigate mobile application screens using react-navigation
.
Prerequisites #
To complete this tutorial, you’ll need:
A local development environment for Node.js. Follow How to Install Node.js and Create a Local Development Environment.
Familiarity with setting up your environment to create a new React Native project and use the iOS or Android simulators may be beneficial.
Note: If you worked with react-navigation
in the past, you might encounter some differences. You can consult the documentation for guides on migrating from 3.x and migrating from 4.x.
This tutorial was verified with Node v14.7.0, npm
v6.14.7, react
v16.13.1, react-native
v0.63.2, @react-navigation/native
v5.7.3, and @react-navigation/stack
v5.9.0.
Step 1 — Creating a New React Native App #
First, create a new React Native app by entering the following command in your terminal:
npx react-native init MySocialNetwork --version 0.63.2
Then, navigate to the new directory:
cd MySocialNetwork
And start the application for iOS:
npm run ios
Alternatively, for Android:
npm run android
Note: If you experience any problems, you may need to consult troubleshooting issues for React Native CLI.
This will create a skeleton project for you. It doesn’t look much like a social network right now. Let’s fix that.
Open up App.js
:
nano App.js
Replace the contents of App.js
with the following code to display a welcome message:
App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Welcome to MySocialNetwork!</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export default App;
Save the file. Now, when you run the application, a Welcome to MySocialNetwork! message will appear in your simulator.
In the next step, you will add more screens to your application.
HomeScreen
and FriendsScreen
>Step 2 — Creating a HomeScreen
and FriendsScreen
#
Currently, you have a single screen displaying a welcome message. In this step, you will create the two screens for your application: HomeScreen
and FriendsScreen
.
HomeScreen
>HomeScreen
#
Your app will need a HomeScreen
. The HomeScreen
will display the number of friends already in your network.
Take the code from App.js
and add it to a new file called HomeScreen.js
:
cp App.js HomeScreen.js
Open HomeScreen.js
:
nano HomeScreen.js
Modify HomeScreen.js
to use HomeScreen
instead of App
:
HomeScreen.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
class HomeScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>You have (undefined) friends.</Text>
</View>
);
}
}
// ...
export default HomeScreen;
This code will produce a You have (undefined) friends. placeholder message. You will provide a value later.
FriendsScreen
>FriendsScreen
#
Your app will also need a FriendsScreen
. On the FriendsScreen
you will be able to add new friends.
Take the code from App.js
and add it to a new file called FriendsScreen.js
:
cp App.js FriendsScreen.js
Open FriendsScreen.js
:
nano FriendsScreen.js
Modify FriendsScreen.js
to use FriendsScreen
instead of App
:
FriendsScreen.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
class FriendsScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Add friends here!</Text>
</View>
);
}
}
// ...
export default FriendsScreen;
This code will produce an Add friends here! message.
At this point, you have a HomeScreen
and FriendsScreen
. However, there is no way to navigate between them. You will build this functionality in the next step.
Step 3 — Using StackNavigator
with React Navigation
#
For navigating between screens, you will use a StackNavigator
. A StackNavigator
works exactly like a call stack. Each screen you navigate to is pushed to the top of the stack. Each time you hit the back button, the screens pop off the top of the stack.
First, install @react-navigation/native
:
npm install @react-navigation/native@5.7.3
Then, install @react-navigation/stack
and its peer dependencies:
npm install @react-navigation/stack@5.9.0 @react-native-community/masked-view@0.1.10 react-native-screens@2.10.1 react-native-safe-area-context@3.1.4 react-native-gesture-handler@1.7.0
Note: If you are developing for iOS, you may need to navigate to the ios
directory and run pod install
.
Next, revisit App.js
:
nano App.js
Add NavigationContainer
and createStackNavigator
to App.js
:
App.js
import 'react-native-gesture-handler';
import React from 'react';
import { StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
const Stack = createStackNavigator();
Then, replace the contents of render
:
App.js
// ...
class App extends React.Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator>
</Stack.Navigator>
</NavigationContainer>
);
}
}
// ...
Nested inside <Stack.Navigator>
, add the HomeScreen
:
App.js
import 'react-native-gesture-handler';
import React from 'react';
import { StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './HomeScreen';
const Stack = createStackNavigator();
class App extends React.Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
}
// ...
This code creates a very small stack for your navigator with only one screen: HomeScreen
.
Nested inside <Stack.Navigator>
, add the FriendsScreen
:
App.js
import 'react-native-gesture-handler';
import React from 'react';
import { StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './HomeScreen';
import FriendsScreen from './FriendsScreen';
const Stack = createStackNavigator();
class App extends React.Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
/>
<Stack.Screen
name="Friends"
component={FriendsScreen}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
}
// ...
This code adds the FriendsScreen
to the navigator.
Note: This differs from how createStackNavigator
was used in previous versions of React Navigation.
Now, the navigator is aware of your two screens.
Adding Buttons to HomeScreen
and FriendsScreen
#
Finally, add buttons to take you between your two screens.
In HomeScreen.js
, add the following code:
HomeScreen.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
class HomeScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>You have (undefined) friends.</Text>
<Button
title="Add some friends"
onPress={() =>
this.props.navigation.navigate('Friends')
}
/>
</View>
);
}
}
// ...
In FriendsScreen.js
, add the following code:
FriendsScreen.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
class FriendsScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Add friends here!</Text>
<Button
title="Back to home"
onPress={() =>
this.props.navigation.navigate('Home')
}
/>
</View>
);
}
}
// ...
Let’s talk about this.props.navigation
. As long as your screen is included in the StackNavigator
, it automatically inherits many useful props from the navigation
object. In this case, you used navigate
to move to a different page.
If you open your simulator now, you can navigate between the HomeScreen
and FriendsScreen
.
Context
to Pass Data to Other Screens>Step 4 — Using Context
to Pass Data to Other Screens
#
In this step, you will create an array of possible friends — Alice
, Bob
, and Sammy
— and an empty array of current friends. You will also create functionality for the user to add possible friends to their current friends.
Open App.js
:
nano App.js
Add possibleFriends
and currentFriends
to the component’s state:
App.js
// ...
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
possibleFriends: [
'Alice',
'Bob',
'Sammy',
],
currentFriends: [],
}
}
// ...
}
// ...
Next, add a function to move a possible friend into the list of current friends:
App.js
// ...
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
possibleFriends: [
'Alice',
'Bob',
'Sammy',
],
currentFriends: [],
}
}
addFriend = (index) => {
const {
currentFriends,
possibleFriends,
} = this.state
// Pull friend out of possibleFriends
const addedFriend = possibleFriends.splice(index, 1)
// And put friend in currentFriends
currentFriends.push(addedFriend)
// Finally, update the app state
this.setState({
currentFriends,
possibleFriends,
})
}
// ...
}
// ...
At this point, you have finished building the functionality to add friends.
FriendsContext
to App
>Adding FriendsContext
to App
#
Now you can add friends in App.js
, but you will want to add them to FriendsScreen.js
and have them display in HomeScreen.js
. Since this project is built with React, you can inject this functionality into your screens with context.
Note: In previous versions of React Navigation, it was possible to use screenProps
to share data between screens. In the current version of React Navigation, it is recommended to use React Context to share data between screens.
To avoid a circular reference, you will want a new FriendsContext
file:
nano FriendsContext.js
Export FriendsContext
:
FriendsContext
import React from 'react';
export const FriendsContext = React.createContext();
Open App.js
:
nano App.js
Add the FriendsContext
:
App.js
import 'react-native-gesture-handler';
import React from 'react';
import { StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { FriendsContext } from './FriendsContext';
import Home from './Home';
import Friends from './Friends';
const Stack = createStackNavigator();
class App extends React.Component {
// ...
render() {
return (
<FriendsContext.Provider>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
/>
<Stack.Screen
name="Friends"
component={Friends}
/>
</Stack.Navigator>
</NavigationContainer>
</FriendsContext.Provider>
);
}
}
// ...
This code establishes FriendsContext
as a new Context
object and wraps the NavigationContainer
in a Context.Provider
component so any children in the component tree can subscribe to context changes.
Since you are no longer using View
or Text
, it is possible to remove those imports from react-native
.
You will need to provide a value
to make data accessible by consumers:
App.js
// ...
class App extends React.Component {
// ...
render() {
return (
<FriendsContext.Provider
value={
{
currentFriends: this.state.currentFriends,
possibleFriends: this.state.possibleFriends,
addFriend: this.addFriend
}
}
>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
/>
<Stack.Screen
name="Friends"
component={Friends}
/>
</Stack.Navigator>
</NavigationContainer>
</FriendsContext.Provider>
);
}
}
// ...
This will allow the HomeScreen
and FriendsScreen
to reference any context changes to currentFriends
and possibleFriends
.
Now you can work on referencing the context in your screens.
FriendsContext
to HomeScreen
>Adding FriendsContext
to HomeScreen
#
In this step, you will set up the application to display the current friend count.
Open HomeScreen.js
:
nano HomeScreen.js
And add the FriendsContext
:
HomeScreen.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { FriendsContext } from './FriendsContext';
class HomeScreen extends React.Component {
// ...
}
HomeScreen.contextType = FriendsContext;
// ...
This code establishes a Class.contextType
. You can now access context in your screens.
For instance, let’s make your HomeScreen
display how many currentFriends
you have:
HomeScreen.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { FriendsContext } from './FriendsContext';
class Home extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>You have { this.context.currentFriends.length } friends!</Text>
<Button
title="Add some friends"
onPress={() =>
this.props.navigation.navigate('Friends')
}
/>
</View>
);
}
}
HomeScreen.contextType = FriendsContext;
// ...
If you open your app up again in the simulator and view the HomeScreen
, you will see the message: You have 0 friends!.
FriendsContext
to FriendsScreen
>Adding FriendsContext
to FriendsScreen
#
In this step, you will set up the application to display the possible friends and provide buttons for adding them to the current friends.
Next, open FriendsScreen.js
:
nano FriendsScreen.js
And add the FriendsContext
:
FriendsScreen.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { FriendsContext } from './FriendsContext';
class FriendsScreen extends React.Component {
// ...
}
FriendsScreen.contextType = FriendsContext;
// ...
This code establishes a Class.contextType
.
Now, create a button to add friends in FriendsScreen.js
:
FriendsScreen.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { FriendsContext } from './FriendsContext';
class Friends extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Add friends here!</Text>
{
this.context.possibleFriends.map((friend, index) => (
<Button
key={ friend }
title={ `Add ${ friend }` }
onPress={() =>
this.context.addFriend(index)
}
/>
))
}
<Button
title="Back to home"
onPress={() =>
this.props.navigation.navigate('Home')
}
/>
</View>
);
}
}
FriendsScreen.contextType = FriendsContext;
// ...
If you open your app up again in the simulator and view the FriendsScreen
, you will see a list of friends to add.
If you visit the FriendsScreen
and click on the button to add friends, you will see the list of possibleFriends
decrease. If you visit the HomeScreen
, you will see the number of friends increase.
You can now navigate between screens and share data between them.
Conclusion #
In this tutorial, you have created a sample React Native application with multiple screens. Using React Navigation, you devised a way to navigate between screens. Using React Context, you developed a way to share data between screens.
The complete source code for this tutorial is available on GitHub.
If you want to dig deeper into React Navigation, check out their documentation.
React Navigation is not the only routing and navigation solution. There is also React Native Navigation, React Native Router Flux, and React Router Native.
If you’d like to learn more about React, take a look at our How To Code in React.js series, or check out our React topic page for exercises and programming projects.