在 Redux 中没有 React Navigation 状态的 React Native 中的 Redux

Posted

技术标签:

【中文标题】在 Redux 中没有 React Navigation 状态的 React Native 中的 Redux【英文标题】:Redux in React Native without React Navigation state in Redux 【发布时间】:2018-05-02 20:17:29 【问题描述】:

我在 React Navigation 网站上看到了Redux Integration page,但我不明白为什么我们需要将导航状态存储在 Redux 存储中,我们不能将应用程序的状态存储在 Redux 中并让导航器保持自己的状态吗?

因为整合router.getStateForAction()router.getActionForPathAndParams()看起来很复杂。

我有一些疑问,比如我们是否应该为我们拥有的每个网名使用getStateForAction()?为他们每个人创建一个减速器? 我们是否应该对根导航器内其他导航器内的嵌套屏幕执行相同操作? 那么我们什么时候应该使用router.getActionForPathAndParams()

谢谢

【问题讨论】:

【参考方案1】:

没有必要在reducer中存储导航状态。如果您不需要,只需将应用程序状态保持在 reducer 和导航状态即可。然后你可以像这样集成 Redux:

// App.js

import React from 'react';
import  Provider  from 'react-redux'
import RootNavigator from './src/navigation/RootNavigation';
import configureStore from './src/stores/configureStore';

const store = configureStore();

export default class App extends React.Component 
  render() 
    return (
      <Provider store=store>
        <RootNavigator />
      </Provider>
    );
  

但实际上,在 Redux 中集成导航状态并没有那么复杂。如果您这样做,导航状态将在您在屏幕之间导航时自动更新。它在复杂的应用程序中非常有用。因此,我将尝试向您解释如何将 React Navigation 和 Redux 一起使用,也许您将来会发现它很有用。

首先,你配置你的 StackNavigator as usual:

// navigation/RootNavigator.js

const HomeScreen = () => (
  <View style= flex: 1, alignItems: 'center', justifyContent: 'center' >
    <Text>Home Screen</Text>
  </View>
);

const RootNavigator = StackNavigator(
  Home: 
    screen: HomeScreen,
  ,
);

export default RootNavigator;

然后你去reducers文件夹(如果你有的话)并创建navReducer.js

 // reducers/navReducer.js

import RootNavigator from '../navigation/RootNavigation';

const initialState = RootNavigator.router.getStateForAction(RootNavigator.router.getActionForPathAndParams('Home'));

const navReducer = (state = initialState, action) => 
  const nextState = RootNavigator.router.getStateForAction(action, state);

  // Simply return the original `state` if `nextState` is null or undefined.
  return nextState || state;
;

我们使用RootNavigator.router.getStateForAction 只是为了获取导航状态并将其设置为新reducer 的初始状态。

然后将reducer与其他的组合起来:

// reducers/index.js

Import navReducer from ‘./navReducer’;

const appReducer = combineReducers(
  nav: navReducer,// updated was nav:nav,
  ...
);

现在我们只需要修改我们的App.js。现在它看起来像:

import React from 'react';
import  Provider, connect  from 'react-redux';
import  addNavigationHelpers  from 'react-navigation';
import RootNavigator from './src/navigation/RootNavigation';
import configureStore from './src/stores/configureStore';
const store = configureStore();

class AppComponent extends React.Component 
  render() 
    return (
      <RootNavigator navigation=addNavigationHelpers(
        dispatch: this.props.dispatch,
        state: this.props.nav,
      ) />
    );
  


const mapStateToProps = (state) => (
  nav: state.navReducer
);

const AppContainer = connect(mapStateToProps)(AppComponent);

export default () => 
  return (
    <Provider store=store>
      <AppContainer />
    </Provider>
  )

因此,您不需要用addNavigationHelpers 包装每个组件,只需根组件即可。在屏幕之间导航时,您不需要发送/管理操作。它将自动更新。

【讨论】:

我仍然头晕目眩并试图理解,我错过的一些关键点是每个嵌套导航器都需要获得 navigationHelpers,需要用“connect()”包装,需要有一个reducer 并且需要将状态传递到它的 props 中。我认为只有***导航器需要它。第二点,我在他们的 github 上检查了示例 react navigation redux 项目,但它在他们的 reducer 中有很多逻辑,我认为我必须自己通过操作来减少导航数据,但很简单,但是 router.getStateForAction() 会自动执行此操作。还在检查,现在该睡觉了! 你不需要用addNavigationHelpers包装每个组件,只需要根组件。在屏幕之间导航时,您不需要发送/管理操作。它将自动更新。正如我所说,没有必要在 reducer 中存储导航状态。因此,如果您的应用程序很简单并且您不需要额外的逻辑 - 只需使用我的第一个示例。 不是每个组件,而是每个导航器...您确定根导航器下的每个导航器都不应该用 addNavigationHelpers 包装吗? 说实话,我没有组合导航器的经验。你总是可以提出一个关于这个的问题。我很确定如果你提出一个关于组合反应导航器并将它们的状态存储在 Redux 中的问题,你会找到答案!但是,如果我们回到我们的主题,是的,可以使用 redux 而不在 reducer 中存储导航状态,并且您不需要在每个屏幕上都使用 getStateForAction()。祝你好运!

以上是关于在 Redux 中没有 React Navigation 状态的 React Native 中的 Redux的主要内容,如果未能解决你的问题,请参考以下文章

为啥初始状态没有保留在 react-redux 中

Redux - 状态正在更新,但 React 组件没有

有没有办法在 react-router-redux@5.0.0 中定义默认路由(如果没有匹配)

React-redux 操作没有被调度

如何在没有 Redux 的情况下将状态保存在本地存储 React 中?

加载指示器出现但在 react-redux 中没有移动