Wrapping React Navigation navigators in Redux Containers

Michael Ceber
2 min readJun 2, 2020

Sometimes you need access to your global redux state inside the navigationOptions function defined in each navigator.

For example you might want to hide the bottom navigator easily from deep within a nested navigator or component. It is virtually impossible to crawl up the tree and try do this using parameters and navigator state.

Trust me I tried for hours and it was a mess!

Another example might be your connection to the internet has dropped off and such state is available in redux, and perhaps what ever navigator is currently focused or perhaps showing but far up the tree needs to all change colour as a result. Need a simple easy way to do this.

So how to access the redux state and have any changes applied to the navigation components?

Simple, wire the redux state into the screenProps which is available to use via the navigation options. When the redux state changes, screenProps also changes and the navigator is rendered.

So for example below the title is set to the value stored in redux at ui.Title

navigationOptions: ({ navigation, screenProps }) => {
return {
title: screenProps.ui.Title
};

To do this take for example the classical creation of the stack navigator

const navigator = createStackNavigator(
{
...
}

To wire this into redux easily we use a reusable helper function

const navigator = CreateConnectedNavigatorWithState(createStackNavigator(
{
...
})

In this example every navigator needs access to the ‘ui’ slice of redux so I was able to reuse the same function throughout the application and it looks like this: (a bit verbose due to the typescript!)

import { NavigationStackProp } from "react-navigation-stack";
import { connect } from "react-redux";
import { IGlobalState } from "../types/state/IGlobalState";
export interface IProps {
screenProps: { ui: IGlobalState["ui"] };
}
export interface IOwnProps {
navigation: NavigationStackProp;
}
export type INavigatorWrapperComponentProps = IProps & IOwnProps;const mapStateToProps = (state: IGlobalState, ownProps: IOwnProps): IProps => ({ screenProps: { ui: state.ui } });export const CreateConnectedNavigatorWithState = (component: any) => connect(mapStateToProps)(component);

If you have different requirements throughout your application then it might make sense to write a bespoke mapStateToProps for every connected component.

That is it! Works a treat. Time to remove all those crazy untyped cross cutting setParam and state.param calls!

Enjoy!

--

--

Michael Ceber

Fullstack .net, c#, typescript, react developer etc…