我通常使用以下模式构建组件:
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的最佳实践,而只是通过state
和dispatch
作为我组件的道具:
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存储中使用了哪些属性。我对此很好。
所以我的问题是:
在绕过mapStatetoProps方面,我还有其他考虑吗?我担心的是,由于只有一个state
属性,每当Redux存储中的任何属性发生更改时,React都会过分地重新渲染每个组件。这就是为什么有必要在mapStateToProps中手动映射属性吗?
跳过mapDispatchToProps并利用默认注入的this.props.dispatch
,我会失去什么?我必须做“额外的”工作才能直接在mapDispatchToProps中映射状态。我会为此付出什么?
在React + Redux设置中还有其他代码组织/模式可帮助减少组件属性的混乱吗?
谢谢!只是把我的头缠在这些工具上。这是一个有趣的练习,但是有些事情有些古怪!
答案 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用例,包括商店设置,定义化简,不可变的更新逻辑,检查意外突变,甚至自动创建状态的整个“切片”,而无需手动编写任何动作类型或动作创建者。 >