【问题标题】:How can i access to redux store with react navigation?如何通过反应导航访问 redux 商店?
【发布时间】:2020-06-03 18:19:21
【问题描述】:

我有应用程序“音乐应用程序”供两个用户输入“访客,已注册用户”

我有一个底部导航器, 当访客打开我的应用程序时,我只想呈现 4 个底部选项卡“主页、浏览、搜索、广播”。

但是当用户登录/注册时,我想呈现 5 个标签,之前的标签加上“库”标签。

所以

我在用户 register\login 时调度操作,并将 isLogin 状态从 false 更改为 true 并执行一些操作,例如添加一些其他数据到我的抽屉里,看起来还不错,

我想访问 react-navigation 文件“Tabs.js”中的redux store,

我想从mapStateToProps 访问状态,但我无法从非类组件访问this.props.isLogin!

所以我不知道如果我不使用 Class 组件怎么办!

那么有没有办法在 Tabs.js 文件中使用“连接 HOC”来访问 redux 存储?

代码

Tabs.js 文件

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));

为 Drew Reese 编辑答案

当我尝试以这种方式进行操作时,我收到了错误消息

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);

错误信息

这个导航器有导航和容器属性,所以它是 不清楚它是否应该拥有自己的状态。移除道具:“isLogin, dispatch" 如果导航器应该从导航中获取其状态 支柱。如果导航器应该保持自己的状态,不要通过 导航道具。

我尝试了什么

我把所有的堆栈都放了

“抽屉、堆栈、底部标签”

在一个文件“类组件”中,它可以工作,但正如@Drew 所说,这样做不是一个好主意:)

这里有一个gist 文件,如果你想看的话

【问题讨论】:

  • 这看起来一点也不正确 - 在您访问“this.props”时的倒数第二行中,您不在组件内,因此“this.props”不应该存在。
  • @Izkata 我知道,所以我的问题是如何访问此文件中的this.props :)
  • 这个新警告我们的错误源自什么/在哪里?
  • 如果不是尝试在您定义导航器的地方连接您的 redux 存储,以便您可以选择性地呈现一个或另一个选项卡,而是将该逻辑移动到一个“选项卡”组件,该怎么办?连接到你的 redux 商店?这将取消混合 connect HOC 注入的 isLogin 和 dispatch 道具。如果这对您有用,我可以更新我的答案。它甚至可以进一步减少,因为您的两个“选项卡”对象之间存在大量代码重复。
  • @DrewReese 我们正在等待:3

标签: javascript reactjs react-native redux react-navigation


【解决方案1】:

您需要创建动态路由,以及一个根据用户是否登录来呈现选项卡的组件。在Tabs.js 中执行以下操作。

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

【讨论】:

  • 如果您遇到问题,请在此处查看我的答案stackoverflow.com/questions/56392339/…
  • 我的应用程序正在运行,但没有底部标签,我收到此警告 Functions are not valid as a React child. This may happen if you return a Component instead of &lt;Component /&gt; from render. Or maybe you meant to call this function rather than return it.
  • 向const HomeScreen = ({ isLogin, login, logout, navigation }) =&gt; { 等组件添加导航,请参阅我更新的示例。
  • @OliverD 这就是我在您的问题的最后评论中所描述的。
【解决方案2】:

我认为你的意思是让App 成为一个组件。在这种情况下,它是一个函数组件,所以没有this,你还需要返回有效的 JSX。

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

请注意,我已经对 notLoginTabs 组件进行了 PascalCased 处理以符合 React 规范,并将它们作为 JSX 返回,并带有 props 传播。

如果子组件不关心isLogin,则在传递道具之前将其解构。这会清理代码并且不会将不必要的道具传递给孩子。

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

编辑

创建一个选项卡组件,其中包含已验证和未验证的选项卡。

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)

在AppTest

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

【讨论】:

  • 感谢您的回复,我在您编写代码时处理了我的代码,但出现此错误TypeError: Cannot read property 'undefined' of undefined
  • @OliverD 该错误引用了哪一行代码?您在哪里尝试访问具有“未定义”作为属性的对象?
  • 是的,我知道指的是什么,我只是根据我按下的底部选项卡更改标题标题,所以我现在评论它,所以这些错误消失了,但我得到了新错误,请再次检查我的问题
猜你喜欢
  • 1970-01-01
  • 2016-07-14
  • 1970-01-01
  • 2020-04-22
  • 1970-01-01
  • 1970-01-01
  • 2020-10-09
  • 2019-06-22
  • 1970-01-01
相关资源
最近更新 更多