减少React-Redux状态和调度样板

时间:2019-01-16 18:14:52

标签: javascript reactjs redux react-redux

我通常使用以下模式构建组件:

import selectors from '../store/selectors'
import someAction1 from '../actions/someAction1'
import someAction2 from '../actions/someAction2'
import someAction3 from '../actions/someAction3'

class MyComponent extends React.Component {
  render() => {
    return <Fragment>
      <div>{this.props.someReduxProperty1}</div>
      <div>{this.props.someReduxProperty2}</div>
      <div>{this.props.someReduxProperty3}</div>
      <a onClick={this.props.someAction1}>Action1</a>
      <a onClick={this.props.someAction2}>Action2</a>
      <a onClick={this.props.someAction3}>Action3</a> 
    </Fragment>
  }
}

export default connect(
  (state, ownProps) => {
    return {
      someReduxProperty1: selectors.getSomeReduxProperty1(state),
      someReduxProperty2: selectors.getSomeReduxProperty2(state),
      someReduxProperty3: selectors.getSomeReduxProperty3(state)
    }
  },
  (dispatch) => {
    return {
      someAction1: () => {
        dispatch(someAction1())
      },
      someAction2: () => {
        dispatch(someAction2())
      },
      someAction3: () => {
        dispatch(someAction3())
      }
    }
  }
)(MyComponent)

这确实完成了工作,但即使在这个简短的示例中,我感觉我也在重复键入相同的内容。当我的容器组件正常工作时,它们会变得很冗长。另外,我发现我经常修改组件中使用的属性和操作的列表,这使得不断重新键入所有内容变得有些沮丧。我读到的有关react + redux的大多数示例似乎都反映了此代码设置。

这真的有必要吗?我正在考虑忽略似乎是React + Redux的最佳实践,而只是通过statedispatch作为我组件的道具:

import selectors from '../store/selectors'
import someAction1 from '../actions/someAction1'
import someAction2 from '../actions/someAction2'
import someAction3 from '../actions/someAction3'

class MyComponent extends React.Component {
  render() => {
    const { state, dispatch } = this.props
    return <Fragment>
      <div>{selectors.getSomeReduxProperty1(state)}</div>
      <div>{selectors.getSomeReduxProperty2(state)}</div>
      <div>{selectors.getSomeReduxProperty3(state)}</div>
      <a onClick={() => { dispatch(someAction1()) }}>Action1</a>
      <a onClick={() => { dispatch(someAction2()) }}>Action2</a>
      <a onClick={() => { dispatch(someAction3()) }}>Action3</a>
    </Fragment>
  }
}

export default connect(
  (state, ownProps) => {
    return { state: state }
  }
  /* dispatch gets added by default */
)(MyComponent)

该代码仅对变量名进行了最少的重复。另外一个好处是,由于每个组件的connect调用都是相同的,所以我可以连接一个助手,甚至可以进一步缩短我的组件:

export default connectHelper = (componentClass) => {
  return connect((state) => {
    return { state: state }
  })(componentClass)
}
class MyComponent extends React.Component {
  ...
}

export default connectHelper(MyComponent)

我确实无法通过浏览connect调用一眼就能看到Redux存储中使用了哪些属性。我对此很好。

所以我的问题是:

  1. 在绕过mapStatetoProps方面,我还有其他考虑吗?我担心的是,由于只有一个state属性,每当Redux存储中的任何属性发生更改时,React都会过分地重新渲染每个组件。这就是为什么有必要在mapStateToProps中手动映射属性吗?

  2. 跳过mapDispatchToProps并利用默认注入的this.props.dispatch,我会失去什么?我必须做“额外的”工作才能直接在mapDispatchToProps中映射状态。我会为此付出什么?

  3. 在React + Redux设置中还有其他代码组织/模式可帮助减少组件属性的混乱吗?

谢谢!只是把我的头缠在这些工具上。这是一个有趣的练习,但是有些事情有些古怪!

1 个答案:

答案 0 :(得分:4)

是的,有很多方法可以缩短这个时间。

首先,您应该使用the "object shorthand" form of mapDispatch

const mapDispatch = {
    someAction1,
    someAction2,
    someAction3,
};

第二,虽然我们没有mapState的“对象简写”,但是您可以使用Reselect的createStructuredSelector API来做同样的事情。

是的,如果您传递整个state值,您的组件现在将重新渲染,以每次更新到Redux存储。 React-Redux does a lot of work internally to make sure your own component only re-renders when needed,它基于您的mapState函数返回的值。

第三,考虑在组件开始时使用分解来提取它们所需的特定道具,因此您不必在每一行都重复this.props.。这可以是在类组件的render()方法中进行对象分解,也可以是对功能组件进行功能参数分解。

最后,虽然它不是特定于React的,但请查看我们新的redux-starter-kit package。它包含的实用程序可简化几种常见的Redux用例,包括商店设置,定义化简,不可变的更新逻辑,检查意外突变,甚至自动创建状态的整个“切片”,而无需手动编写任何动作类型或动作创建者。 >

相关问题