Welcome back!

Today I’m going to explain how you can get control of your app navigation in redux, integrating redux with react-navigation.

For this tutorial example I’m going to use ExpoSDK, a solution to build react-native apps without native folders. ExpoSDK gives us a bunch of components and services so we don’t need to link native modules. It drives developers to create react-native apps with zero lines of native code!

react-navigation

react-navigation represents the combining effort from Facebook, Expo and the react community in building an easy-to-use and performance navigation library. It supports web and mobile and in the future, it will deprecate NavigationExperimental, the official solution to navigation provided by react-native.

Sample App

Our focus here is to build an app with nested navigators and integrate them in our redux-store.

This will let you change screens and navigation state in a navigator reducer, with that accomplished your screen components won’t need to know specific navigation logic. And that’s what we want, agnostic, reusable and testable components.

With that in mind, we’re going to build a quick app to get some football leagues and their respective team’s games for this season. For the sake of simplicity all data will be stored in objects since data fetching is out of the scope of the tutorial.

Thats what we want to achieve:

A league screen where the user can select the team:

A team screen where the user can see the team matches:

And a navigation drawer that changes the current league.

Let’s go!

Redux

First, let’s setup redux. For that we will need at least 2 reducers plus our navigator’s reducers.

League reducer;

Team reducer;

Navigation reducer (stack navigator && drawer navigator).

As far as we know, we will need an actions file for each reducer, a screen container and a screen component.

Here is my folder structure:

As you can see, I have my usual redux folder structure setup, with an additional folder for routing and two extra files to configure and provide redux-store to my app components. The db folder is where I store my database objects.

I skipped the league actions file as I will build the action that will change to the current league screen in navigation reducer.

With redux ready, let’s prepare react-navigation.

Navigators

Our app will have two navigators, a drawer and a stack.

DrawerNavigator let us navigate between screens using a side drawer.

StackNavigator is used for routing through screens where each new screen is placed on top of a stack.

In our app, we’ll use DrawerNavigator to navigate between leagues and StackNavigator to navigate through league and team match screens.

These are the steps we need to get there:

Define navigation configuration and respective component for each navigator we want to use and pass the navigation prop to our navigators.

Build the reducer that will handle each of navigators changes.

Place root navigator component as parent component of your app.

Code

Now, I’m going to iterate through the previous task list with code examples, if you want to see in detail here is the link of GitHub repository with all app code.

1 — Navigation configs & components

We have to define our configuration for each navigators, mainly this configuration represents the routes that will be available in navigator and the Screen component attached to it.

Let’s talk first about the StackNavigator we need. We’ll need to navigate through two screens, each representing a route of our navigator:

League screen (screen with league teams);

Team matches screen (screen with team matches).

It will lead to this:

With navigation configuration ready we can start to thinking about building the component that will hold our desired navigator.

Without redux, this step is not necessary, since we are only writing a component to connect the router in navigator to redux-store.

What we need here, is a component that receives navigation, dispatch props, and shares those with our previous navigator.

As we are talking about a StackNavigator, we can place the back button listener in this component to get the Android back button normal behaviour in our app.

Now let’s dive in the same process to setup our Drawer.

DrawerNavigator will have the responsibility to navigate through different leagues from different countries. Although we want different routes, the screen component will always be the same, our previous stack navigator component! And this is where the react-navigation magic happens - the ease to nest navigators - so whenever I click in a drawer tab, I want one StackNavigator composed by those two screens to be rendered. So lets define it:

With the navigation configuration set, we can follow the same process to build our navigator wrapper component.

2 — Navigation reducers

If you’ve read the code snippets in previous step you’ll notice that I’m connecting my components with my redux-store, with reducers called drawer and stack. Those are the reducers responsible to update our app navigation state.

Now we’re going to write them in navigation.js in reducers folder.

React-navigation provide us a method for each navigator that returns the corresponding state changes, all we need to know is the actual state and the changes we want to made that corresponds to our action.

This is the simplest reducer we can have for our purposes — when a navigation action arrives, it reduces the next state and returns it.

Ok, now we have our navigator’s states saved in our redux store. With the help of NavigationActions from react-navigation we can build our navigation logic in the reducer.

Now the navigation of our app can be changed in the reducer, which means that for it to change we’ll have to dispatch actions and define what we want to change.

Let’s setup the action that will make the change of league to team match screen. An action called ‘getTeam’ will need a type to recognize it in the navigators reducers and a name to identify the team and the respective league.

With the action created let’s define the changes we want to watch in our state:

And thats’s it! We’ve just changed our current screen in the reducer! And that’s not all, explore NavigationActions to see the list of available pre-made actions. But do not stick with it, if you have the state you can change it yourself if the available actions don’t fit your needs.

3 — Place root navigator component as parent component

With all of our configuration details and reducer changes ready, now we can render this desired navigation to the screen, you just need to place your root navigator component as parent of our App, in our case called ‘DrawerNavigation’.

So, for that, we’ll need to configure the redux-store, provide it to our app that will hold our drawer navigator.

And that’s all for today! Checkout out the repo project #1, it has a lot of extra code and will let you understand the logic of navigation with redux.

I hope you’ve learn something and if you have any questions feel free to comment!

Happy coding! 👨‍💻

Stay tuned for React-Native Tutorial #2 — Testing redux apps with Jest/Enzyme