redux文档声明当使用redux with react时,使用connect
包中的react-redux
。这不应该是shouldComponentUpdate
- http://redux.js.org/docs/basics/UsageWithReact.html#implementing-container-components
Redux库的connect()函数,它提供了许多有用的优化来防止不必要的重新渲染。 (这样做的一个结果是您不必担心自己实施shouldComponentUpdate的React性能建议。)
然而,我的组件是不必要地更新的,因为即使数组的内容相同,我每次都会返回一个新数组。这是我的代码:
const AssetManagerSmart = connect(
function(state) {
const { assets } = state;
return {
assetIds: assets.map( asset => asset.id )
}
}
)
请参阅此assetIds
,它是来自redux状态的数组的映射。这导致我的组件重新渲染。为了简化上面的代码,我们可以想象assetIds
每次都被分配给一个新的浅层相等的数组,如下所示:
const AssetManagerSmart = connect(
function(state) {
const { assets } = state;
return {
assetIds: ['hi']
}
}
)
当我遇到上述情况时,医生怎么说我不应该shouldComponentUpdate
?上面我看到每个人都在做,即使在"用反应"关于官方redux文档的部分。
答案 0 :(得分:2)
当connect处于默认的pure
模式时,它会执行several checks,旨在避免调用mapStateToProps
,如果它被调用,则在没有任何更改的情况下阻止重新包装的组件。< / p>
要检查它是否应该运行mapStateToProps
(和mergeProps
)连接进行2次相等检查:
areStatesEqual
- 检查整个状态是否使用严格相等进行更改。只要商店发生变化,这将返回false
。但是,您可以覆盖它,以检查商店的某个部分是否发生了变化。在您的情况下,您可能想要检查assets
是否已更改:
(next, prev) => prev.assets === next.assets
areOwnPropsEqual
- 进行浅层相等检查,以查看提供给从connect返回的组件的props是否已更改。由于您不使用道具,理论上您可以覆盖它以始终返回true
,但这样可以完全避免重新发布道具更改。
如果调用mapStateToProps
,则执行2次检查以查看是否应重新渲染包装的组件:
areStatePropsEqual
- mapStateToProps
当前和之前结果之间的浅层相等。这将检查上一个{ assetIds: [] }
是否等于{ assetIds: [] }
,并且由于更改的assetsIds
数组将返回false
。
areMergedPropsEqual
- mergeProps
当前和之前结果之间的浅层相等 - 合并ownProps
,mapStateToProps
,mapDispatchToProps
。
因此,如果您的状态发生变化或道具发生变化,系统会调用mapStateToProps
,assetIds
会重新计算。您可以覆盖areStatesEqual
和areOwnPropsEqual
,仅将应调用的特定更改列入白名单{.1}}。
mapStateToProps
的结果将与之前的结果进行浅层检查。您可以覆盖检查以实际查看mapStateToProps
中的项目是否已更改,但这可能很昂贵,您在assetIds
中也需要相同。更简单的选择是使用memoized选择器。
通知选择器
选择器可以占用商店的一部分,并计算派生数据。只要状态的相关部分没有改变,memoized选择器将返回相同的结果(不执行计算)。由于结果是相同的数组(不是具有相似值的新数组),因此将通过areMergedPropsEqual
和areStatePropsEqual
检查(除非发生其他更改)。
Reselect是一个帮助您创建记忆选择器的库。
这就是为资产创建备忘选择器的方法。 ids(未经测试):
areMergedPropsEqual