Using Navigators #

Mobile apps rarely consist of just one screen. As soon as you add a second screen to your app, you will have to take into consideration how the user will navigate from one screen to the other.

You can use navigators to transition between multiple screens. These transitions can be typical side-to-side animations down a master/detail stack, or vertical modal popups.

Navigator #

React Native has several built-in navigation components, but for your first app you will probably want to use Navigator. It provides a JavaScript implementation of a navigation stack, so it works on both iOS and Android and is easy to customize.

Working with Scenes #

At this point you should feel comfortable rendering all sorts of components in your app, be it a simple View with Text inside, or a ScrollView with a list of Images. Together, these components make up a scene (another word for screen) in your app.

A scene is nothing other than a React component that is typically rendered full screen. This is in contrast to a Text, an Image, or even a custom SpinningBeachball component that is meant to be rendered as part of a screen. You may have already used one without realizing it - the "HelloWorldApp", the "FlexDirectionBasics", and the "ListViewBasics" components covered earlier in the tutorial are all examples of scenes.

For simplicity's sake, let's define a simple scene that displays a bit of text. We will come back to this scene later as we add navigation to our app. Create a new file called "MyScene.js" with the following contents:

import React, { Component } from 'react'; import { View, Text, Navigator } from 'react-native'; export default class MyScene extends Component { static get defaultProps() { return { title: 'MyScene' }; } render() { return ( <View> <Text>Hi! My name is {this.props.title}.</Text> </View> ) } }

Notice the export default in front of the component declaration. This will export the component, and in turn allow other components to import it later on, like so:

import React, { Component } from 'react'; import { AppRegistry } from 'react-native'; import MyScene from './MyScene'; class YoDawgApp extends Component { render() { return ( <MyScene /> ) } } AppRegistry.registerComponent('YoDawgApp', () => YoDawgApp);

We now have a simple app that renders your scene and nothing else. In this case, MyScene is a simple example of a reusable React component.

Using Navigator #

Enough about scenes, let's start navigating. We will start by rendering a Navigator, and then let the Navigator render the scene for you by passing in your own render function to its renderScene prop.

render() { return ( <Navigator initialRoute={{ title: 'My Initial Scene', index: 0 }} renderScene={(route, navigator) => { return <MyScene title={route.title} /> }} /> ); }

Something you will encounter a lot when dealing with navigation is the concept of routes. A route is an object that contains information about a scene. It is used to provide all the context that the navigator's renderScene function needs to render a scene. It can have any number of keys to help distinguish your scene, and I happened to pick a single title key for the above example.

Pushing scenes onto the stack #

In order to transition to a new scene, you will need to learn about push and pop. These two methods are provided by the navigator object that is passed to your renderScene function above. They can be used, as you may have realized, to push and pop routes into your navigation stack.

navigator.push({ title: 'Next Scene', index: 1, }); navigator.pop();

A more complete example that demonstrates the pushing and popping of routes. Edit your index*.js file to look something like this:

import React, { Component } from 'react'; import { AppRegistry, Navigator } from 'react-native'; import MyScene from './MyScene'; class SimpleNavigationApp extends Component { render() { return ( <Navigator initialRoute={{ title: 'My Initial Scene', index: 0 }} renderScene={(route, navigator) => <MyScene title={route.title} // Function to call when a new scene should be displayed onForward={() => { const nextIndex = route.index + 1; navigator.push({ title: 'Scene ' + nextIndex, index: nextIndex, }); }} // Function to call to go back to the previous scene onBack={() => { if (route.index > 0) { navigator.pop(); } }} /> } /> ) } } AppRegistry.registerComponent('SimpleNavigationApp', () => SimpleNavigationApp);

And your MyScene.js to match this:

import React, { Component, PropTypes } from 'react'; import { View, Text, TouchableHighlight } from 'react-native'; export default class MyScene extends Component { render() { return ( <View> <Text>Current Scene: {this.props.title}</Text> <TouchableHighlight onPress={this.props.onForward}> <Text>Tap me to load the next scene</Text> </TouchableHighlight> <TouchableHighlight onPress={this.props.onBack}> <Text>Tap me to go back</Text> </TouchableHighlight> </View> ) } } MyScene.propTypes = { title: PropTypes.string.isRequired, onForward: PropTypes.func.isRequired, onBack: PropTypes.func.isRequired, };

In this example, the MyScene component is passed the title of the current route via the title prop. It displays two tappable components that call the onForward and onBack functions passed through its props, which in turn will call navigator.push() and navigator.pop() as needed.

Check out the Navigator API reference for more Navigator code samples, or read through the Navigation guide for other examples of what you can do with navigators.

High Five! #

If you've gotten here by reading linearly through the tutorial, then you are a pretty impressive human being. Congratulations. Next, you might want to check out all the cool stuff the community does with React Native.

You can edit the content above on GitHub and send us a pull request!