Updated September 21, 2016

React Native Basics: Using react-native-router-flux

Originally publish on medium.com.

A core component of any app is navigating between different routes/screens/scenes. I’ve analyzed different navigation solutions in the past but this week I wanted to spend some time doing common routing tasks using a package I’ve used a lot lately, react-native-router-flux.

Today we’ll walk through setting up your routes, routing between scenes in a “normal” way, setting up tabs, and using a modal.

This is a very basic overview and everything I cover can be found in the official documentation but I found those a little overwhelming when first getting started — this is the guide I wish I had when I first started.

Let’s get to it…

Setup

First thing we’ll do is set up our react native project and then install the react-native-router-flux package.

react-native init ReactNativeRouterFluxDemo
cd ReactNativeRouterFluxDemo
npm install --save react-native-router-flux

We’ll then set up our project so we can easily write for both iOS and Android

mkdir app

Then create our entry point at app/index.js

app/index.js

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

const App = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.welcome}>Welcome to the Demo!</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

export default App;

Finally, we want to point both index.ios.js and index.android.js to our new, cross-platform, entry point. Replace both files with the following

index.*.js

import { AppRegistry } from 'react-native';
import App from './app/index';

AppRegistry.registerComponent('ReactNativeRouterFluxDemo', () => App);

Cool! Boring setup out of the way. Here’s what you should see.

0

Navigating Between Scenes

This videos covers setting up our first few screens. It’s the same as the content in the next few paragraphs.

So we’ve got a standard React Native app now. But we want to have two screens. A scarlet screen and a gray screen. First let’s create ScarletScreen.js and GrayScreen.js. I’m only going to post the snippet for one, the only difference is the text, component name, and backgroundColor. Check out the full repo if you get stuck.

app/ScarletScreen.js

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

const ScarletScreen = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.welcome}>Scarlet Screen</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#bb0000',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
    color: '#ffffff',
  },
});

export default ScarletScreen;

This videos covers navigating between scenes and configuring react-native-router-flux. It’s the same as the content in the next few paragraphs.

So we’ve got these two screens set up, how do we display them? That’s where react-native-router-flux comes in. There’s just a bit of boilerplate you have to do for this and I’ll explain everything after you take a look at the code snippet. The following is happening in app/index.js

app/index.js

import React, { Component } from 'react';
import { Router, Scene } from 'react-native-router-flux';

import ScarletScreen from './ScarletScreen';
import GrayScreen from './GrayScreen';

const App = () => {
  return (
    <Router>
      <Scene key="root">
        <Scene
          key="scarlet"
          component={ScarletScreen}
          title="Scarlet"
          initial
        />
        <Scene key="gray" component={GrayScreen} title="Gray" />
      </Scene>
    </Router>
  );
};

export default App;

We’re doing a few things here, first of all requiring the necessary components. After that you’ll see a Router component which is what we want to end up returning. Then we’ve got our first Scene, which is the nomenclature that the package uses. It’s convention to wrap all your other scenes in a root scene.

Then you can see the actual scenes we use to display our components. They’ve got the bare minimum props to render, that being the key (you’ll see how we use that in a moment), the component, and the title (which is used in the navbar).

So how do we navigate between scenes?

We’re going to rely on the Actions export from react-native-router-flux. Whenever we want to go to a new screen we’re going to call Actions.[KEY] where [KEY] is the key we passed into the scene when we defined it. Let’s see it in use.

app/ScarletScreen.js

import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Actions } from 'react-native-router-flux'; // New code

const ScarletScreen = () => {
  return (
    <View style={styles.container}>
      <Text
        style={styles.welcome}
        onPress={() => Actions.gray()} // New Code
      >
        Scarlet Screen
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#bb0000',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
    color: '#ffffff',
  },
});

export default ScarletScreen;

You can see how we’re using Actions on line 16. You should now be able to do some navigating!

Note that the lag is due to the GIF recording.

So from just a few lines of code we can navigate between two screens, on iOS or Android, and we got a Navbar for free. If you want some more information check out the mini-tutorial in the docs of react-native-router-flux.

Tabs

This videos covers setting up our tabs. It’s the same as the content in this section.

Before we actually set up our tabs let’s set up some more screens so we can use them once the tabs are actually set up. They’re all essentially the same, just changing the component variable name, backgroundColor, and component text.

Create the following files with the following background colors (apologies to everyone for the colors, I was going for a theme).

There are quite a few files added here so check out this commit for all the changes included here. Here’s the app/ folder after the additions.

.
├── BlackScreen.js
├── BlueScreen.js
├── GoldScreen.js
├── GrayScreen.js
├── MaizeScreen.js
├── ScarletScreen.js
└── index.js

So we’ve got all of our screens set up, Now we can actually create the tab bar.

It’s really easy to set up tabs — all you have to do is add the tabs prop to a scene property. It will then turn each child into its own tab. Each tab will have its own navbar and hold its own navigation state. We’ll see that in a bit, first let’s write the code.

We’re going to have 3 tabs in our app, each with two nested screens. I’m just posting a snippet below but you can see the full file here.

app/index.js

// Removed for brevity

const TabIcon = ({ selected, title }) => {
  return <Text style={{ color: selected ? 'red' : 'black' }}>{title}</Text>;
};

const App = () => {
  return (
    <Router>
      <Scene key="root">
        {/* Tab Container */}
        <Scene
          key="tabbar"
          tabs={true}
          tabBarStyle={{ backgroundColor: '#FFFFFF' }}
        >
          {/* Tab and it's scenes */}
          <Scene key="osu" title="OSU" icon={TabIcon}>
            <Scene key="scarlet" component={ScarletScreen} title="Scarlet" />
            <Scene key="gray" component={GrayScreen} title="Gray" />
          </Scene>
          {/* Removed for brevity */}
        </Scene>
      </Scene>
    </Router>
  );
};

We can see here that we took our initial scenes and nested them within a “tab” scene. We also set up a basic component to handle the tab icons (or in our case tab text). The full file has the other tabs but I challenge you to add those so you can experience setting up the tabs, then reference the code.

Here’s what we’ve got now.

Again, the lag is due to the GIF recording software.

Modal

This videos covers setting up our modal. It’s the same as the content in this section.

Cool! So we’ve got 3 tabs and each tab has 2 scenes nested inside of it. But what if we want a modal that pops up over all of those — hiding the tab bar and navbar? In reality this isn’t a modal but rather another scene that we’re adding. The package has a different type of modal that you can use if you desire. Here’s what our goal is going to be.

I really need to use something different for GIFs…

As you can (hopefully) see when we press “Open Modal” a screen pops up overtop of everything else and does so by animating up from the bottom. It’s simple and so is the implementation. First thing I had to do was create a ModalScreen component which is just like all of our others. Then, in app/index.js, I added the following

app/index.js

// Removed for brevity

<Scene
  key="modal"
  direction="vertical"
  component={ModalScreen}
  title="Modal"
  hideNavBar
/>

You can see that’s the absolute minimum. The full updates can be seen in this commit. We’re specifying the same props as all other scenes (key, component, and title) the only addition being direction which is what’s allowing us to bring the screen up from the bottom and hideNavBar which is hiding the navbar — good naming on the package author’s part :)


That’s a brief introduction to using the react-native-router-flux package — it will likely handle a lot of your navigation needs. Using a well maintained, well liked package, built on top of NavigationExperimental will be much easier to do than if you try to roll your own. If you want to dive deeper into what you can do with this package be sure to checkout the official docs.

React Native School Logo

React Native School

Want to further level up as a React Native developer? Join React Native School! You'll get access to all of our courses and our private Slack community.

Learn More