【问题标题】:How to use Redux and React navigation to make a global counter如何使用 Redux 和 React 导航制作全局计数器
【发布时间】:2020-04-02 02:37:56
【问题描述】:

我正在制作一个 React-Native 应用程序,其中我有一个来自 React Navigation 的导航器,并且我还想实现 Redux。我正在尝试创建一个基于参数更新的全局计数器。 以下是操作:

export const setFlags = (value) => {
return {
    type: 'SETFLAGS',
    value
}

}

export const setNonFlags = (value) => {
    return {
        type: 'SETNONFLAGS',
        value
    }
}

这里是 reducer,因为它有两个功能相同的东西,我认为一个可以工作(我是 Redux 的新手):

   const initialState = {
    flags:0,
    nonFlags:0,

}

const AllFlagReducer = (state = initialState, action) =>{
    switch(action.type){


        case 'SETFLAGS':
            return state.flags = state.flags + action.value
        case 'SETNONFLAGS':
            return state.nonFlags = state.nonFlags + action.value

    }
    return state
}

export default AllFlagReducer

这是我想将“flag”和“nonFlag”的本地状态发送到 redux 全局状态的按钮。之后我重置本地状态并移动到下一个屏幕。

<TouchableOpacity style={styles.resetButton}
            onPress= {
              // dispatch something like flags(in redux):this.state.flags
              // dispatch nonFlags(in redux): this.state.nonFlags
              () =>{this.resetAll();
              navigation.navigate('Specific Scams')

            }}>

我们将不胜感激。 更新 1: 整个组件:

class ScamTree extends React.Component {
constructor(props){
  super(props)
  this.state = {
    flags : 0,
    nonFlags: 0,
    qAnswered:0
  }
}

可能重要的功能:

resetAll = () =>{
  this.setState({flags:0})
  this.setState({nonFlags:0})
  this.setState({qAnswered:0})

}

按钮,(我没有为按钮制作单独的组件):

<TouchableOpacity style={styles.resetButton}
            onPress= {
              // dispatch something like flags:this.state.flags
              // dispatch nonFlags: this.state.nonFlags
              () =>{this.resetAll();store.dispatch({type:"SETFLAGS",value:5})
              navigation.navigate('Specific Scams')

            }}>

            <Text style={{paddingHorizontal:40}}>NEXT</Text>
          </TouchableOpacity>

使 React Navigation 工作的导出:

export default function(props) {
const navigation = useNavigation();

return <ScamTree {...props} navigation={navigation} />;

}

【问题讨论】:

  • 那么您需要什么帮助?你有动作,reducer...假设你已经配置了你的 redux 存储和提供者,你现在只需要连接组件并使用值调度动作。
  • 如果所有这些都是正确的,你介意展示如何创建一个组件来完成这个吗?我尝试了“useDispatch”并编写了一个单独的功能组件,但由于这是一个类组件,它没有工作。
  • 介意分享TouchableOpacity的整个组件代码吗?然后很简单地展示如何使用connect HOC 将其连接到您的商店。
  • @DrewReese 我更新了帖子以显示类、函数、touchableOpacity 和导出,但我没有为按钮制作单独的组件,因为它在类中使用了一些本地状态。谢谢

标签: reactjs react-native redux react-navigation


【解决方案1】:

在您的 .js 类中,您必须像这样绑定您的操作

  import { bindActionCreators } from 'redux'
  import { connect } from 'react-redux';

  <TouchableOpacity style={styles.resetButton}
        onPress= {
          // dispatch something like flags(in redux):this.state.flags
          // dispatch nonFlags(in redux): this.state.nonFlags
          () =>{
          this.resetAll();
          this.props.commanAction.setFlags(your value);
          this.props.commanAction.setNonFlags(your value);
          navigation.navigate('Specific Scams')

        }}>

  const mapDispatchToProps = dispatch => {
      return {
         commanAction: bindActionCreators(commanAction, dispatch)
      };
   };

  export default connect(mapStateToProps, mapDispatchToProps)(Your .js className);

其他代码看起来不错。

【讨论】:

  • 谢谢,但是使用类组件中的 React 导航,我必须像这样导出类:export default function(props) { const navigation = useNavigation();返回 ; },那么我该如何连接呢?
  • connect HOC 中的 mapDispatchToProps 在调用调度 using bindActionCreators 时包装(绑定)每个动作,因此显式使用 bindActionCreators 是完全没有必要。 react-redux.js.org/api/connect#object-shorthand-form
【解决方案2】:

如果我在另一个答案中理解了你的评论,以及你的问题更新的 sn-p,我相信你需要装饰 这个 功能组件:

export default function(props) {
  const navigation = useNavigation();

  return <ScamTree {...props} navigation={navigation} />;
}

你想用connect HOC 装饰这个组件,以将它连接到你的redux store。

首先我将该函数转换为新的withNavigation HOC:

const withNavigation = WrappedComponent => props => {
  const navigation = useNavigation();
  return <WrappedComponent{...props} navigation={navigation} />;
};
withNavigation.displayName = `withNavigation(${WrappedComponent.displayName || 'Component'})`;

现在你可以如下装饰ScamTree

export default withNavigation(ScamTree);

但现在你还需要将你的动作创建者连接到你的 redux 商店,用react-reduxconnect HOC 装饰它:

const mapDispatchToProps = {
  setFlags,
  setNonFlags,
};

export default withNavigation(
  connect(null, mapDispatchToProps)(ScamTree),
);

注意:我看到您似乎在本地状态中存储了一些标志值,不确定这是否相关,但您可以使用 mapStateToProps 作为连接的第一个参数而不是在初始状态中映射空。

到目前为止,您可能已经注意到每个新的 HOC 都会创建一些 嵌套,并且随着使用的 HOC 越多,这种情况会变得更糟。解决方案是使用reduxcompose HOC。没错,它不仅仅是为商店编写中间件。它可以将所有装饰器组合成一个 HOC 来包装您导出的组件,或者换句话说,它可以展平/消除嵌套。

Tips

compose 所做的只是让你编写深度嵌套的函数 没有代码向右漂移的转换。不要给它 功劳太大了!

...
import { compose } from 'redux';
...

class ScamTree extends Component { ... }

const mapDispatchToProps = {
  setFlags,
  setNonFlags,
};

export default compose(
  withNavigation,
  connect(null, mapDispatchToProps),
)(ScamTree);

注意:您的 reducer 需要始终返回 new 状态对象引用并且从不 改变现有状态。此外,尽管您的返回确实可以正常工作,但 reducer 模式是在默认 switch 案例中返回未处理的操作类型:

const AllFlagReducer = (state = initialState, action) => {
  switch(action.type){
    case 'SETFLAGS':
        return { ...state, flags: state.flags + action.value };

    case 'SETNONFLAGS':
        return { ...state, nonFlags: state.nonFlags + action.value };

    default:
      return state;
  }
}

【讨论】:

  • 非常感谢!
【解决方案3】:

现在,在您的 reducer 案例中,您在整个状态上写入新状态,而不是在状态对象的合适位置,它可以这样写


const AllFlagReducer = (state = initialState, action) =>{
 switch(action.type){
    case 'SETFLAGS':
        return { ...state, flags: state.flags + action.value }
    case 'SETNONFLAGS':
        return { ...state, nonFlags: state.nonFlags + action.value }
    default: return state
     }
    }
export default AllFlagReducer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-17
    • 1970-01-01
    • 2020-09-29
    • 2016-08-14
    • 1970-01-01
    相关资源
    最近更新 更多