Oliver D
Oliver D

Reputation: 2889

How can i access to redux store with react navigation?

I have App "Music App" for tow users type "Guest, a user registered"

I have a bottom navigator for those, When Guest opens my app I want to render just 4 bottom tabs "Home, browse, search, radio".

but when user login/register I want to render 5 tabs previously tabs plus "Library" Tab.

SO

I dispatch action when user register\login, and change isLogin state from false to true and work some stuff like add some other data to my drawer and it appears fine tho,

I want to access to redux store inside react-navigation File "Tabs.js",

I want to access state from mapStateToProps but I can't access this.props.isLogin from non-class component!

So I don't have any idea how can I do it if i don't use Class component!

So is there a way to access to redux store using "connect HOC" inside Tabs.js file?

Code

Tabs.js file

import {connect} from 'react-redux';
import {store} from '../redux/store/store';

const LoginTabs = createBottomTabNavigator({....}); // For user '5 tabs'

const notLoginTabs = createBottomTabNavigator({....}); // For Guest '4 tabs'



const App = this.props.isLogin ? LoginTabs : notLoginTabs; // Not work i know :P

export default (createAppContainer(App));

EDIT For Drew Reese Answer

When I try to do it in this way I got under error message

const mapStateToProps = state => {
  console.log('state', state);
  return {
    isLogin: state.user.isLogin,
  };
};

const App = ({isLogin, ...props}) =>
  isLogin ? <LoginTabs {...props} /> : <NotLoginTabs {...props} />;
const Root = createAppContainer(App);

export default connect(mapStateToProps)(Root);

Error message

This navigator has both navigation and container props, so it is unclear if it should own its own state. Remove props: "isLogin, dispatch" if the navigator should get its state from the navigation prop. If the navigator should maintain its own state, do not pass a navigation prop.

What I tried

I put all Stacks

"Drawer, Stacks, BottomTabs"

inside One File "Class Component" and it's work but as @Drew say It's not a good idea to do it in this way :)

Here's a gist file if you want to see it

Upvotes: 0

Views: 4017

Answers (2)

Drew Reese
Drew Reese

Reputation: 202801

I think you meant to make App a component. In this case it'd be a functional component, so no this, and you also need to return valid JSX.

const App = props => props.isLogin ? (
    <LoginTabs {...props} />
  ) : (
    <NotLoginTabs {...props} />
  );

Notice I've PascalCased the notLoginTabs component to be react compliant, and returning them as JSX with props spread in.

If the child components don't care about isLogin then destructure it out before passing props. This cleans up the code and doesn't pass unnecessary props on to children.

const App = ({ isLogin, ...props }) => isLogin ? (
    <LoginTabs {...props} />
  ) : (
    <NotLoginTabs {...props} />
  );

EDIT

Create a tabs component which houses your authenticated and unauthenticated tabs.

const LoginTabs = createBottomTabNavigator( ... );
const NotLoginTabs = createBottomTabNavigator( ... );

const Tabs = ({ isLogin, ...props }) => isLogin ? (
    <LoginTabs {...props} />
  ) : (
    <NotLoginTabs {...props} />
  );

const mapStateToProps = state => ({
  isLogin: state.user.isLogin,
});

export default AuthTabs = connect(mapStateToProps)(Tabs)

In AppTest

...
const AppNavigator = createStackNavigator(
  {
    TabHome: {
      screen: AuthTabs,
...

Upvotes: 0

Junius L
Junius L

Reputation: 16132

You need to create dynamic routes, and one component that renders tabs based on whether the user is logged in or not. in Tabs.js do the following.

const loginRoutes = {
  Home: {
    screen: Home,
    navigationOptions: {
      title: 'Home',
    },
  },
  Browse: {
    screen: Browse,
    navigationOptions: {
      title: 'Browse',
    },
  },
  Search: {
    screen: Search,
    navigationOptions: {
      title: 'Search',
    },
  },
  Radio: {
    screen: Radio,
    navigationOptions: {
      title: 'Radio',
    },
  },
  Library: {
    screen: Library,
    navigationOptions: {
      title: 'Library',
    },
  },
}

const noLoginRoutes = {
  Home: {
    screen: Home,
    navigationOptions: {
      title: 'Home',
    },
  },
  Browse: {
    screen: Browse,
    navigationOptions: {
      title: 'Browse',
    },
  },
  Search: {
    screen: Search,
    navigationOptions: {
      title: 'Search',
    },
  },
  Radio: {
    screen: Radio,
    navigationOptions: {
      title: 'Radio',
    },
  }
}

const mapStateToProps = state => {
  return {
    isLogin: state.user.isLogin,
 };
};


 const AppNav = ({ isLogin }) => {
  const Container = createAppContainer(
    createDrawerNavigator(
      {
        ...drawerRoutes,
        App: createStackNavigator(
          {
            ...routes,
            Tabs: createBottomTabNavigator(
              isLogin ? loginRoutes : noLoginRoutes
            ),
          },
          routesConfig
        ),
      },
      drawerConfig
    )
  );

  return <Container />;
};

export default connect(mapStateToProps)(AppNav);

DEMO

Upvotes: 5

Related Questions