Routing with React Navigation in React Native

Zeb Girouard

In this article, we will learn how to navigate mobile app screens using react-navigation in a React Native application.

React Native offers us a way to build native mobile apps with the React framework. If React Native is new to you, we recommend looking at Alligator’s Getting Started with React Native article.

React Navigation is a popular library for routing and navigation in a React Native app.

Why React Navigation?

React Navigation is a JavaScript-based library for routing. It’s officially promoted by both Facebook and the React Native documentation as the primary solution for routing. React Navigation is certainly not the only available option. To learn more about additional options, skip to the Other Routing Options section at the bottom of this article.

Getting Set Up

MySpace and Facebook have held the social media throne for too long. Today, we will disrupt the market with the next big social network, called MyAlligatorFace. 🐊

First, create a new React Native app:

$ create-react-native-app MyAlligatorFace

$ cd MyAlligatorFace
$ npm start

This will create a skeleton project for us, but it doesn’t look much like a social network yet.

Let’s fix that. If we open up App.js, we can tell the world how many friends we have on MyAlligatorFace:

App.js

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        We have no friends!
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

* Note that the above code snippet is taken from the Create React Native App project, licensed under BSD 3-Clause “New” or “Revised” License and is copyright 2017 by Create React Native App Contributors. You can find a copy of the license here.


No friends simulator image


Home Page

Oof, we don’t have any friends! That hurts a bit, but soon we will be connected to all of our friends.

Our app will need two screens: a Home screen and a Friends screen. In the Home screen we will see the friends already in our network and in the Friends screen we will be able to add new friends.

To get started, take the code from App.js and add it to a new file called Home.js:

Home.js

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default class Home extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        We have no friends!
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

To navigate to the Home page, we will create a StackNavigator.

StackNavigator with React Navigation

A StackNavigator works exactly like a call stack or a stack of dishes. Each screen we navigate to is pushed to the top of the stack, and each time we hit the back button, this screen pops off the top of the stack.

First, install react-navigation:

$ npm install --save react-navigation

Next, create a file called AppNavigator.js:

AppNavigator.js

import { createStackNavigator } from 'react-navigation';
import Home from './Home';

const AppNavigator = createStackNavigator({
  Home: { screen: Home },
});

export default AppNavigator;

This creates a very small stack for our navigator, with only one screen: Home.

Our display content is currently inside App.js. If we simply put our StackNavigator inside App.js, our app will be modular and much cleaner. From there we add additional screens to their respective files.

App.js

import React from 'react';
import AppNavigator from './AppNavigator';

export default class App extends React.Component {
  render() {
    return (
      <AppNavigator/>
    );
  }
}

After saving we still see the same content, but sadly we still have no friends. Let’s make a page to change that!

Friends Page

First create a page similar to Home.js called Friends.js:

Friends.js

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default class Friends extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        Add friends here!
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

Next, add it to our navigator:

AppNavigator.js


  import { createStackNavigator } from 'react-navigation';
  import Home from './Home';
  import Friends from './Friends';

  const AppNavigator = createStackNavigator({
    Home: { screen: Home },
    Friends: { screen: Friends},
  });

  export default AppNavigator;

Finally, add buttons to take us between our two screens.

In Home.js, add the following code:

Home.js

import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';

export default class Home extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        We have no friends!
        <Button
          title="Add some friends"
          onPress={() =>
            this.props.navigation.navigate('Friends')
          }
        />
      </View>
    );
  }

  const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: '#fff',
      alignItems: 'center',
      justifyContent: 'center',
    },
  });

In Friends.js, add something similar:

Friends.js

import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';

export default class Friends extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        Add friends here!
        <Button
          title="Back to home"
          onPress={() =>
            this.props.navigation.navigate('Home')
          }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

Let’s talk about that this.props.navigation piece. Where did that come from?

That’s the great part about react-navigation: as long as our screen is included in our StackNavigator, it automatically inherits many useful props from the navigation object. We just used one of them, navigate, to move to a different page, but we can do much more than that. For example, we can look at the navigation history and pull out parameters from other pages.

If we open our simulator now, we can navigate between the Home and Friends page with ease!


Home screen and friends screen


Now for the final step, let’s get some friends! 💪

Adding Friends

In App.js, add an array of possible friends and an array of current friends to the component’s state:

App.js


  import React from 'react';
  import AppNavigator from './AppNavigator';

  export default class App extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        possibleFriends: [
          'Allie',
          'Gator',
          'Lizzie',
        ],
        currentFriends: [],
      }
    }

    render() {
      return (
        <AppNavigator/>
      );
    }
  }

Next, add a function to move a “possible friend” into the list of “current friends”:

App.js


  import React from 'react';
  import AppNavigator from './AppNavigator';

  export default class App extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        possibleFriends: [
          'Allie',
          'Gator',
          'Lizzie',
        ],
        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 our app state
      this.setState({
        currentFriends,
        possibleFriends,
      })
    }

    render() {
      return (
        <AppNavigator/>
      );
    }
  }

Passing Logic to Other Screens

Now we can add friends in App.js, but we want to add them in Friends.js and have them show in Home.js. Since this project is built with React.js, we can inject this functionality into our screens with props.

First, pass these screenProps into AppNavigator:

App.js


  import React from 'react';
  import AppNavigator from './AppNavigator';

  export default class App extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        possibleFriends: [
          'Allie',
          'Gator',
          'Lizzie',
        ],
        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 our app state
      this.setState({
        currentFriends,
        possibleFriends,
      })
    }

    render() {
      return (
        <AppNavigator
          screenProps={ {
            currentFriends: this.state.currentFriends,
            possibleFriends: this.state.possibleFriends,
            addFriend: this.addFriend,
          } }
        />
      );
    }
  }

Then we can access them in our screens. For instance, let’s make our Home screen actually tell us how many currentFriends we have:

Home.js

import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';

export default class Home extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        We have { this.props.screenProps.currentFriends.length } friends!
        <Button
          title="Add some friends"
          onPress={() =>
            this.props.navigation.navigate('Friends')
          }
        />
      </View>
    );
  }

  const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: '#fff',
      alignItems: 'center',
      justifyContent: 'center',
    },
  });

Zero friends now


Look at that mathematical precision!

Now we need to add our friends in Friends.js to round out our app:

Friends.js

import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';

export default class Friends extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        Add friends here!
        {
          this.props.screenProps.possibleFriends.map((friend, index) => (
            <Button
              key={ friend }
              title={ `Add ${ friend }` }
              onPress={() =>
                this.props.screenProps.addFriend(index)
              }
            />
          )
        )
        }
        <Button
          title="Back to home"
          onPress={() =>
            this.props.navigation.navigate('Home')
          }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

If we open our app up again in the simulator, we can see our friends to add!

“Allie” and “Gator” are our roommates, so let’s add them! Unfortunately, we haven’t had the pleasure of meeting “Lizzie” yet, so this is what we’ll see on our home page:


Zero friends now


We have friends now!! 🦄✨ 🚀

Conclusion

In addition to creating the newest and hottest social media app, MyAlligatorFace, we also covered the following:

  • react-navigation
  • StackNavigator
  • Giving our React Native app a modular design with screens
  • Passing screenProps into different screens

If you are stuck on any part of this walkthrough, you can see the final version on GitHub.

This is only the beginning. If you want to dig deeper into React Navigation, check out their documentation.

And if you want to dig deeper into a robust app design with MyAlligatorFace, stay tuned for posts on adding authentication and state management to this app with Redux.

Don't forget to add me on MyAlligatorFace or your social media of choice! Or at least share this post if it was helpful! 🐊

Postscript: Other Routing Options

React Navigation has some major competitors. Listed below are the key players with a brief explanation of why we didn’t choose them for this application:

  1. React Native Navigation by Wix is a great solution for those looking for a more native look, feel, and performance. However, it does not work with Expo, the library we introduced in our React Native Getting Started Guide. This requires diving into Xcode or Android Studio immediately, which ties the hands of a developer a bit, and isn’t great for an introductory guide.

  2. React Native Router Flux, built on top of React Navigation has some additional features like flexible nav bar customization and better support for MobX, using observers. We did not see the need to introduce this so early, but it may serve developers as their projects get more complex.

  3. Airbnb’s Native Navigation is still not production-ready yet, and it may never be from the looks of recent GitHub issues

  4. React Router Native is a robust, full-featured router implementation that mimics that of react-router-dom. Much like React Navigation, it has easily navigable documentation. If you are really familiar with react-router-dom from React.js, we recommend trying this library. But for this introduction, we are sticking close to Facebook’s official React Native routing documentation.

  Tweet It

🕵 Search Results

🔎 Searching...