根据我从Dan Abramov的egghead视频'javascript-redux-colocating-selectors-with-reducers'以及他的一些推文中所理解的,使用选择器将状态映射到道具并删除此逻辑是一个好习惯。从Component并将其放在Reducer(管理状态)中。
虽然这很有意义,但每次将新状态添加到存储时,它也会导致我的组件呈现,即使只更改了状态对象的非相关属性。有没有办法在不使用重选器的情况下克服这个问题,对于更简单的情况,这可能有点过分了?
您可能知道,每次更新商店时都会调用mapStateToProps
。
组件是否将重新渲染取决于mapStateToProps
返回的内容。 (实际上,它取决于mapStateToProps
和mapDispatchToProps
返回的组合道具对象。)
React Redux(提供connect
函数的库)对返回的对象和最后返回的对象进行浅等式检查。如果相等性检查成功(即,确定先前返回的对象等于下一个返回的对象),则该组件将不会重新呈现。如果检查失败,则组件将重新呈现。
例如,假设您始终从mapStateToProps
返回以下对象:
{
items: [],
}
这个对象永远不会等于它自己([] === []
返回false
,因为它们是不同的数组)。因此,相等性检查将失败,组件将重新呈现。
但是,React Redux执行更复杂的等式检查(可以找到shallowEqual
的here函数的实现)。
例如,即使{ a: 'b' } === { a: 'b'}
返回false
(它们是不同的对象),shallowEqual
也会将它们视为相等。这是因为shallowEqual
会将返回对象的每个键与先前返回的对象的每个键进行比较,但只有一个深度。更多细节可以在我上面链接的实现中找到。
总之,如果您不希望重新呈现组件,则需要确保相等性检查成功。
您可以:
shouldComponentUpdate
这些建议直接来自Redux的FAQ页面:https://redux.js.org/docs/faq/ReactRedux.html#react-rendering-too-often
您还可以确保mapStateToProps
函数返回shallowEqual
认为相等的对象(例如,没有数组的对象,只有一个深度)。
为简单起见,我会选择Reselect。
简短的回答是:不,不是。
但是,当您使用选择器时,会出现导致组件不必要渲染的常见错误。您应始终确保定义一次选择器。那是什么意思呢?
使用connect方法时,可以将mapStateToProps方法作为参数传递。此方法返回的对象将作为props传递给组件,如果在此对象中定义选择器,则每次组件接收到prop时都会重新定义。这是一个例子:
像这样定义选择器可能会导致组件不必要地渲染。这是因为每次将prop传递给组件时,您基本上都在重新定义getSettings方法。
@connect(state => ({
getSettings: ()=>'sample output',
}))
class Sample extends React.Component {}
正确的方法是像这样定义你的选择器,这样它只会被创建一次并且引用通过你的mapStateToProps参数。
const getSettings = () =>'sample output';
@connect(state => ({
getSettings,
}))
class Sample extends React.Component {}