I have added an update to this article in the end, Do check it out

The React-Native community is finally settling for React-Navigation as the default navigation solution. React-Navigation has a vast and powerful API and one of the best thing is that React-Navigation provides really great support for redux, but the bad news which I personally felt is a lack of proper documentation. In this article I try to explain the basics of integrating React-Navigation with Redux and finally introducing authentication flow to the app. I have divided this writing in two parts, Part-1 contains the basic setup for integrating redux & react-navigation, Part-2 contains the logical flow for authentication. Both the parts are contained in this article.

Prerequisites

To continue reading you should have experience with at least React-Native, React-Navigation, Redux. I haven’t used any authentication API(that isn’t a issue in the demo, the flow will be same as a real world app) in the demonstration app. In Real world situation you will need something like redux-thunk etc. I have used Redux-Persist to mimic the real-world behaviour of persisting user session.

PART-1: Setting up React-Navigation with redux

The whole idea of integrating React-Navigation with redux is to manage navigation state in redux. Thus we can manage all of the app state from the global redux store easily.

In Part-1 we will be integrating redux and React-navigation by creating a navigation reducer which will handle the state for the navigation and add the redux’s dispatch method to handle action’s dispatched through redux. I have created small demonstrable gists for better step by step understanding, the whole project code for understanding how these little parts integrate in the current PART-1 is available here (repo’s master branch):

shubhnik/redux-react-navigation_redux-react-navigation - React-Native + Redux + Redux-Persist + React Navigation_github.com

First let’s get familiar with some react-navigation’s API, we will use these APIs while integrating redux:

  1. [addNavigationHelpers](https://reactnavigation.org/docs/navigators/custom#addNavigationHelpers) : This API helps us to pass our own navigation prop to the Navigator. The navigation prop passed to the navigator will override the default navigation prop.
  2. [getActionForPathAndParams](https://reactnavigation.org/docs/routers/api#getActionForPathAndParams-path-params)(path, params) : This API receives path(the key defined for a route in Navigator and params and returns an action which is needed to update the navigation state. In simple words it tells us “hey! You need to perform this action to navigate to this path”. Consider the following example, see the console.log below, it indicates to perform a NAVIGATE action to the routeName: ‘screen1’:

3. [getStateForAction(action, state)](https://reactnavigation.org/docs/routers/api#getStateForAction-action-state) : We have calculated the action for navigating to a particular route using getActionForPathAndParams, now we need to update the state of the Navigator to actually navigate to the route. For this, getStateForAction comes handy. It receives the action and the current state of the navigator and returns the new updated state. In simple words it says hey! I am giving you a new navigation state based on the action and the current state you provided to me. It will return null if it couldn’t understand the action provided. Consider this sample demo code just to understand how getStateForAction works:

We have calculated the new state, now we want to pass this state to the Navigator. So lets get the act of integrating redux and react-navigation done:

The above reducer returns the new state for the navigator. newState will be null if an action provided to getStateForAction isn’t understandable, that case could be when we are trying to navigate to a route which is not defined in our navigator AppNavigator.

Here in line 17 in the above code snippet, we have passed the dispatch and state to the navigator. All the routes defined in AppNavigator will receive these state and dispatch.

[NavigationActions](https://reactnavigation.org/docs/navigators/navigation-actions) API of react-navigation returns an action object as shown in the gist above. The returned object is same as that returned by getActionForPathAndParams.

Now we have checked all the parts: a reducer to handle navigation state, passing our own navigation prop to the navigator, dispatching actions to update navigation state. We saw them in gists, now you should check all those parts assembled and working together, understand the flow in here:

shubhnik/redux-react-navigation_redux-react-navigation - React-Native + Redux + Redux-Persist + React Navigation_github.com

PART-2: Implementing authentication flow

In this part we will be creating an authentication flow using redux and react-navigation. We will be following this navigator for reference:

const AppNavigator = StackNavigator({login: {screen: Login},screen1: {screen: Screen1},screen2: {screen: Logout}});

Here is how our authentication flow will work:

We will be using this demonstrable minimal loginReducer to manage our login states:

The most important logic of managing state for authentication flow is managed by our navigation reducer. Our [basicNavigationReducer](https://gist.github.com/shubhnik/b55602633aaeb5919f6f3c15552d1802) has transformed into a little more capable reducer which can handle authentication flow, let’s take a look at our new navigationReducer:

Let’s get through this navigationReducer step by step:

On left we aren’t handling the “@@redux/INIT” and hence the unpleasant header animation, on right we are handling the “@@redux/INIT” action and hence a more natural and a pleasant header animation.

By now we have investigated the navigationReducer which is handling the authentication flow. The authentication flow has been set up now. I have used Redux-Persist for persisting user session. React-Navigation and redux have finally found harmony with authentication flow 😃.

For checking the complete authentication flow and how it plays along, checkout the authFlow branch of this repo for better understanding:

shubhnik/redux-react-navigation_redux-react-navigation - React-Native + Redux + Redux-Persist + React Navigation_github.com

Handling the hardware back button in Android

Since we are handling the navigation state with redux, thus react-navigation loses its control over managing state. Thus we have to handle back button in Android on our own. The official docs of react-navigation has a great documentation for handling back button in Android here:

Redux Integration Guide | React Navigation_Edit description_reactnavigation.org

What’s next?

The most important part of integrating redux with react-navigation is done. Adding more complex nested navigation won’t be any tough task now. I will be adding more demos for nested navigations to the github repo . Don’t forget to star and watch the repo for more updates. You can also fork the repo and share your solutions with the community.

If this guide happens to be useful for you, than do show some love with claps and don’t forget to share it with others 🔔 🎉. You can follow me on twitter where sometimes my tweets have some meaning.

UPDATE

  1. Initially I have used [**@@redux/INIT**](https://github.com/shubhnik/redux-react-navigation/blob/authFlow/src/Reducers/navigationReducer.js#L25) which isn’t a kind of good practice. We shouldn’t deprive redux of its own actions 😢. You can check how I am managing state without using @@redux/Init in the nestedNavigators branch.

2. Since I published this article, I have added two more branches nestedTabs and nestedNavigators demonstrating more complex navigation structure.

3. Discussions/feedbacks are appreciated 😄.