Challenge 5: Navigation

Cool, so the rocket launcher was your first app with multiple “pages”. But simply using manually-controlled component state to manage location state definitely doesn’t scale. Let’s look at a better way to handle navigation.

The finest solution to navigation currently exists as an independent library, react-navigation. We’ll install and use this library below.

Your Objective

Build an app that provides details about some popular SXSW venues.

Here’s an example of what that could look like:

Feel free to make yours prettier! :-)

Setup

Install react-navigation by running npm install react-navigation (or yarn add react-navigation if you have yarn installed). Before you begin, replace the contents of your project’s App.js file with the following:

import React from "react";
import {
  Button,
  Image,
  ScrollView,
  StyleSheet,
  Text,
  TouchableOpacity,
  View
} from "react-native";
import { StackNavigator } from "react-navigation";

const venues = [
  {
    id: 1,
    name: "Austin Convention Center",
    address: "500 E Cesar Chavez",
    imageUrl:
      "https://res.cloudinary.com/simpleview/image/upload/c_fill,f_auto,h_240,q_75,w_300/v1/clients/austin/Austin_Convention_Center_Photo_Credit_Thomas_McConnell_Full_Usage_Permissions_5__7e33dc59-1b4c-4de9-9044-c9d18041cca9.jpg",
    latitude: "30.263569",
    longitude: "-97.739606"
  },
  {
    id: 2,
    name: "JW Marriott",
    address: "110 E 2nd St",
    imageUrl:
      "https://wa2.jetcdn.com/photos/jw-marriott-austin/5vOE_FjZ/architecture-city-downtown-building.jpeg?w=780&h=520&dpr=1",
    latitude: "30.264509",
    longitude: "-97.743470"
  },
  {
    id: 3,
    name: "Westin Austin Downtown",
    address: "310 E 5th St",
    imageUrl:
      "http://www.starwoodhotels.com/pub/media/3899/wes3899po.214266_md.jpg",
    latitude: "30.266620",
    longitude: "-97.740375"
  },
  {
    id: 4,
    name: "Hilton Austin Downtown",
    address: "500 E 4th St",
    imageUrl:
      "http://momvoyage.hilton.com/wp-content/uploads/2014/10/Best-Downtown-Austin-Hotels-Hilton-Austin-e1413228104466-940x564.jpg",
    latitude: "30.265259",
    longitude: "-97.738290"
  },
  {
    id: 5,
    name: "The Driskill",
    address: "604 Brazos St",
    imageUrl:
      "https://assets.hospitalityonline.com/photos/employers/258110/404068_l.jpg",
    latitude: "30.268538",
    longitude: "-97.741633"
  }
];

class HomeScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>Getting Around an App</Text>
        <ScrollView contentContainerStyle={styles.centerContent}>
          <Text style={styles.instructions}>
            Using `react-navigation`, make an app{"\n"}
            that lists the venue names in the `venues` array,{"\n"}
            and allows the user to click to view more information.
          </Text>
          <Text style={styles.subtext}>See below for inspiration:</Text>
          <Image
            style={styles.targetImage}
            source={{
              uri:
                "https://monosnap.com/file/GDpr0spLEoewjPiyyAbDC3fjirtL5D.png"
            }}
          />
          <Image
            style={styles.targetImage}
            source={{
              uri:
                "https://monosnap.com/file/R2M8LSTg1ghF7aMclFZXG2e2pTQKrn.png"
            }}
          />
        </ScrollView>
      </View>
    );
  }
}

const RootStack = StackNavigator(
  {
    Home: {
      screen: HomeScreen
    }
  },
  {
    initialRouteName: "Home"
  }
);

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

const styles = StyleSheet.create({
  container: {
    alignItems: "center",
    backgroundColor: "#eee",
    flex: 1,
    justifyContent: "center"
  },
  centerContent: {
    alignItems: "center"
  },
  welcome: {
    fontSize: 20,
    textAlign: "center",
    margin: 10
  },
  instructions: {
    textAlign: "center",
    color: "#333333",
    marginBottom: 10
  },
  subtext: {
    fontSize: 14,
    fontStyle: "italic"
  },
  targetImage: {
    width: 150,
    height: 300,
    marginTop: 25
  }
});

Pointers

The Stack

React Navigation is built around the concept of the navigation stack. You can think of this stack as similar to a browser’s history. As you visit a new page, you add the page to the top of the stack. When you go back, you simply pop the top page off of the stack and return to the page below it in line.

Routes & Screens

React Navigation provides a function, StackNavigator, where you can define how the stack will be managed. Specifically, in this function you will define various routes to “Screen” components, as well as provide configuration like what screen the app should start on.

You’ll notice that we’ve already started the StackNavigator functional call for you. You’ll need to add routes to this.

A route at its simplest is just a map from a name to a component class. Take for example:

Details: {
  screen: DetailsScreen,
}

This would be a route named Details, that when pushed onto the stack would render a DetailsScreen component.

Stack Modification

Each screen component (whose component classes appear in your routes), receives a navigation prop when it is rendered by React Navigation. This prop provides access to all navigation related information actions.

The most basic action you can perform is to navigate to a new route, that is push a new screen onto the navigation stack. this.props.navigation.navigate('Details') This would cause an instance of the component class defined as the screen for the Details route to be rendered.

In addition to manually directing navigation to a certain screen, you can also perform actions on the stack like this.props.navigation.goBack(). This pops the current screen off the stack and renders the previous screen.

Route Params

The utility of these routes would be extremely limited if we were not able to pass data to them. For instance, you may wish to provide a venueId to the DetailsScreen to tell it which venue to showcase. Fortunately we can pass arbitrary data in the form of an object as a second argument when navigating like so: this.props.navigation.navigate('Details', { venueId: 42 }). The data object will then be available in the screen component that is rendered via this.props.navigation.state.params.

React Navigation Docs

Full documentation for React Navigation can be found here: https://reactnavigation.org/docs/hello-react-navigation.html. Jump into the docs to see more examples of use, or to read up on the other functionality it can provide.

Get to it.

When you’re done, post a screenshot of your beautiful app to the #progress channel, then move on to Challenge 6.


Proceed to Challenge 6