React Native NavigationExperimental Part 2 — Implementing Redux

Nader Dabit
React Native Training
6 min readJun 17, 2016

NavigationExperimental is no longer the preferred method of Navigation in React Native, and will soon be deprecated. I would suggest checking out React Navigation with is the current standard and my preferred method of navigation.

This is a continuation of Part 1. We will now be building navigation using React Native Navigation Experimental but adding Redux to manage state.

For part 1, click here.

For part 3, adding tabs, click here.

To see the final working repo, click here.

To get started, we will be beginning with a new React Native project:

react-native init RNExperimentalRedux

We will be using version 0.28.0-rc.0 for this tutorial. If you are on an older version, this code will not work. There were breaking api changes in version 0.28.0-rc.0. Any version after 0.28.0-rc.0 should also work. I will be keeping this repo up to date with any changes.

Then, cd into the project and install redux and react-redux:

npm i redux react-redux --save

Next, let’s set up our project structure.

Create a folder named app:

mkdir app

Then cd into the directory and create the following folders:

cd app
mkdir actions components constants containers reducers store

So now our folder structure should look like this:

First, let’s create our constants that we will use in Redux actions to navigate in the app. We will only need to push and pop for now, so let’s create these constants.

In app/constants, create ActionTypes.js:

Next, let’s create our redux actions that will correlate with these constants. In app/actions create navActions.js:

Now that we have our actions and constants set up, let’s create our navigation reducer and our root reducer. The navigation reducer will only hold our navigation state. We will then use combineReducers in our root reducer to wrap our reducer. This way if we have any future data we would like redux to handle, it will already be set up for us, all we will have to do is add another reducer and import it into our root reducer.

In app/reducers, create the following files: index.js and navReducer.js.

Open navReducer.js and type the following code:

  1. import PUSH_ROUTE and POP_ROUTE actions to use in our reducer
  2. import NavigationExperimental from react-native
  3. We destructure NavigationStateUtils from NavigationExperimental. NavigationStateUtils is basically a helper that lets you call basic routing methods, such as get, indexOf, push, pop, set, and reset among others. NavigationStateUtils.push will basically handle the job of reducing the state and route into a new state. More on this below.

4. We set up an initial state object. In this object, the routes array is going to be the route stack we will be pushing to and popping from .

5. navigationState function does the job of a reducer in conjunction with NavigationStateUtils.Of course you can also manually create a reducer that will do this. There is an example of a manually created route reducer in the project, commented out, here. The navigationState function and the manually created reducer do exactly the same thing.

From NavigationStateUtils, we will only be using the push and pop methods. Here is a link to all of the methods available with NavigationStateUtils.

navigationState takes the current state and returns a new state based on whether a new route is intended to be pushed or popped from the route state.

6. export the navigationState

Now let’s create the root reducer. Open app/reducers/index.js

  1. We import combineReducers from redux like we normally would with any redux application.
  2. We import navReducer
  3. We call combineReducers on our one reducer. If you grow the app later, you can import the rest of the reducers into this file and pass the new reducers into combineReducer.
  4. export the reducer.

We can now create our Redux store. In app/store, create configureStore.js

  1. Import createStore from redux
  2. import our rootReducer
  3. create configureStore function
  4. create variable ‘store’ to hold our redux store
  5. To enable Hot Reloading on Redux stores in React Native, we will just need to use the HMR API similarly to what you’d do on a web project that uses Webpack
  6. return the store

Now we are ready to start building our components. First, let’s create the components that will make up our pages. We will have three stateless components: About, Home, and Button. We will reuse Button in Home and About:

In app/components, create Button.js, About.js, and Home.js:

Button.js:

Button takes onPress and label props.

Home.js:

Home takes a _handleNavigate function that we have yet to define. _handleNavigate will be passed down to Button as a prop.

About.js

About takes a _goBack function that we have yet to define. _goBack will be passed down to Button as a prop.

Now that we have our Components ready to go, we need to create the navRoot of the application The navRoot is basically our entry point to the application. It will be what we bring into our index file and render on application load. Before we can go any further, let’s look at this component.

In app/components, create NavRoot.js:

There is a lot going on here, let’s take a look.

  1. import our normal components and dependencies
  2. import BackAndroid and NavigationExperimental from react-native
  3. destructure NavigationCardStack from NavigationExperimental. If you remember in the last tutorial, we used NavigationCardStack in a similar way that we would use the legacy Navigator component, passing it a renderScene method, navigationState property, and onNavgiate method.
  4. We’re creating a new component called NavState
  5. in _renderScene, we destructure route from props.scene. We switch on the route.key property and return a component based on this value. In our case, we will be checking for either the keys ‘home’ or ‘about’. If you remember in our navReducer, our initialState route had a key of ‘home’, so when the app loads this key will match and Home will be rendered.
  6. _handleNavigate and _handleBackAction will be passed into our About and Home components as props. In these methods, we have access to pushRoute and popRoute methods as this.props. We will define these methods next in our connect function in navRootContainer.js.
  7. Finally, we return the NavigationCardStack and pass in our navigationState, onNavigate, and renderScene methods. this.props.navigate is a property that is passed down from our connect function that we will also define next in our connect function in navRootContainer.js. We also pass in ‘vertical’ as a direction prop. If you do not pass anything here, the default is horizontal.

Next, let’s create our navRootContainer. In app/containers, create navRootContainer.js:

  1. import connect from ‘react-redux’
  2. import NavigationRoot component that we just created from our components folder.
  3. import our push and pop actions
  4. Create the mapStateToProps method. We give the navigator key the property of our navReducer, so it will then be available in the NavigationRoot component as this.props.navigation
  5. We create and export our connect function with our NavigationRoot component, passing in two arguments: mapStateToProps and an object defining the pushRoute and popRoute methods we want to pass down as props. This method can and sometimes is written separately as mapDispatchToProps, which can be used interchangeably:
function mapDispatchToProps (dispatch) {
return {
pushRoute: (route) => dispatch(push(route)),
popRoute: () => dispatch(pop())
}
}

Finally, let’s clean out and rewrite our main entry point. Go to either index.ios.js or index.Android.js and remove the contents of the file. Go ahead and add the below code to the index file:

  1. import react and AppRegistry into our project.
  2. import the configureStore function from configureStore.
  3. Create the store
  4. import the NavigationRootContainer which contains our navigator-experimental component
  5. import Provider from ‘react-redux’
  6. Create our App component using a stateless function.
  7. Register our app.

That’s it! Now you have a starter project using React Native, Navigation Experimental, and Redux. Also you hopefully have a better understanding of the new apis and where they are headed!

Here is the link to the final project.

Thanks for reading (☞゚∀゚)☞

My Name is Nader Dabit . I am a developer at School Status where we help educators make smart instructional decisions by providing all their data in one place. Check us out @schoolstatusapp.

If you like React and React Native, checkout out our podcast — React Native Radio on Devchat.tv

Also, check out my book, React Native in Action now available from Manning Publications

If you enjoyed this article, please recommend and share it! Thanks for your time

--

--

Nader Dabit
React Native Training

Full Stack Product Engineer, Author, Teacher, Director of Developer Relations at Avara