Redux选择器会导致不必要的组件渲染吗?

问题描述 投票:3回答:2

根据我从Dan Abramov的egghead视频'javascript-redux-colocating-selectors-with-reducers'以及他的一些推文中所理解的,使用选择器将状态映射到道具并删除此逻辑是一个好习惯。从Component并将其放在Reducer(管理状态)中。

虽然这很有意义,但每次将新状态添加到存储时,它也会导致我的组件呈现,即使只更改了状态对象的非相关属性。有没有办法在不使用重选器的情况下克服这个问题,对于更简单的情况,这可能有点过分了?

redux selector
2个回答
2
投票

您可能知道,每次更新商店时都会调用mapStateToProps

组件是否将重新渲染取决于mapStateToProps返回的内容。 (实际上,它取决于mapStateToPropsmapDispatchToProps返回的组合道具对象。)

React Redux(提供connect函数的库)对返回的对象和最后返回的对象进行浅等式检查。如果相等性检查成功(即,确定先前返回的对象等于下一个返回的对象),则该组件将不会重新呈现。如果检查失败,则组件将重新呈现。

例如,假设您始终从mapStateToProps返回以下对象:

{
  items: [],
}

这个对象永远不会等于它自己([] === []返回false,因为它们是不同的数组)。因此,相等性检查将失败,组件将重新呈现。

但是,React Redux执行更复杂的等式检查(可以找到shallowEqualhere函数的实现)。

例如,即使{ a: 'b' } === { a: 'b'}返回false(它们是不同的对象),shallowEqual也会将它们视为相等。这是因为shallowEqual会将返回对象的每个键与先前返回的对象的每个键进行比较,但只有一个深度。更多细节可以在我上面链接的实现中找到。

总之,如果您不希望重新呈现组件,则需要确保相等性检查成功。

您可以:

  • 使用reducer将返回的对象保存到状态
  • 使用Reselect缓存结果
  • 手动实现组件中的shouldComponentUpdate

这些建议直接来自Redux的FAQ页面:https://redux.js.org/docs/faq/ReactRedux.html#react-rendering-too-often

您还可以确保mapStateToProps函数返回shallowEqual认为相等的对象(例如,没有数组的对象,只有一个深度)。

为简单起见,我会选择Reselect。


2
投票

简短的回答是:不,不是。

但是,当您使用选择器时,会出现导致组件不必要渲染的常见错误。您应始终确保定义一次选择器。那是什么意思呢?

使用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 {}
© www.soinside.com 2019 - 2024. All rights reserved.