Access redux state in tabnavigator (react-navigation)

Viewed 643

I'm using redux to store some values. One of these values is a boolean named "seen". It's updated to "false" whenever a new message (through websockets) arrive, and when the messages-screen is opened, it's updated to "true" again.

I also have a tabnavigator. In this tabnavigator, I have 4 buttons (icons): Home, Users, Messages and Settings.

Whenever the value of "seen" is "false", I want to show an extra icon in the tabnavigator to show users they have new messages. So I want to have access to the redux store in the tabnavigator.

My tabnavigator code is as follows:

const TabsNavigator = createMaterialTopTabNavigator(
    {
        Home: {
            screen: Home,
            navigationOptions: {
                tabBarIcon: () => (
                    <Icon library="far" icon="home" color="black" size={25} />
                )
            }
        },
        Users: {
            screen: Users,
            navigationOptions: {
                tabBarIcon: () => (
                    <Icon library="far" icon="users" color="black" size={25} />
                )
            }
        },
        Messages: {
            screen: Messages,
            navigationOptions: {
                tabBarIcon: () => {
                    return (
                    <View>
                        // HERE I WANT TO HAVE ACCESS TO THE REDUX STORE (SEEN)
                        // I WANT TO SHOW AN ICON WHEN SEEN = FALSE
                        {seen === false &&
                            <Icon library="far" icon="exclamation" color="black" size={25} />
                        }
                        <Icon library="far" icon="comment" color="black" size={25} />
                    </View>
                )}
            }
        },
        Settings: {
            screen: Settings,
            navigationOptions: {
                tabBarIcon: () => (
                    <Icon library="far" icon="cog" color="black" size={25} />
                )
            }
        }
    },
    {
        initialRouteName: 'Home',
        tabBarPosition: 'bottom',
        tabBarOptions: {
            showIcon: true
        }
    }
)

How can I access the value of "seen" (in the redux store) in the tabnavigator? Adding useSelector(state => state.messages.seen) to the tabnavigator does not work, I get an error saying "hooks can only be called from the body of a functional component".

2 Answers

This is not very recommended, but you can directly access the Redux state if you export the store from the file you configure it in.

e.g

const store = createStore(
  persistedAppReducer, // disregard the actual config
  undefined,
  applyMiddleware(NavMiddleware, LoggerMiddleware, EpicMiddleware)
);

export default store;

Then, you can import this store and get the state like so: store.getState()

I had the same problem and fixed it by creating a FunctionComponent as the tabBarIcon like this:

interface MyIconProps {
  focused: boolean,
}

const MyIcon: React.FunctionComponent<MyIconProps> = ({
  focused,
}) => {
  const count = useSelector(getCount)

  return (
    <View>
      <IconFontAwesome name={"newspaper-o"} size={30} color={focused ? Colors.orange : Colors.darkGrey} />
      { count > 0 && <IconFontAwesome style={{ position: "absolute", top: -5, right: -8 }} name={"circle"} size={20} color={Colors.notificationBadge} /> }
    </View>
  )
}

const MyTab = createStackNavigator(
  {
    MyScreen,
  },
  {
    navigationOptions: ({ navigation, navigationOptions }) => ({
      tabBarIcon: ({ focused }: { focused: boolean }) => <NewsIcon focused={focused} />
    }),
  }
)

Related