避免重新渲染不可能 - 但文档说不应该需要shouldComponentUpdate

时间:2017-08-04 22:13:24

标签: redux react-redux

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文档的部分。

1 个答案:

答案 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当前和之前结果之间的浅层相等 - 合并ownPropsmapStateToPropsmapDispatchToProps

因此,如果您的状态发生变化或道具发生变化,系统会调用mapStateToPropsassetIds会重新计算。您可以覆盖areStatesEqualareOwnPropsEqual,仅将应调用的特定更改列入白名单{.1}}。

mapStateToProps的结果将与之前的结果进行浅层检查。您可以覆盖检查以实际查看mapStateToProps中的项目是否已更改,但这可能很昂贵,您在assetIds中也需要相同。更简单的选择是使用memoized选择器。

通知选择器

选择器可以占用商店的一部分,并计算派生数据。只要状态的相关部分没有改变,memoized选择器将返回相同的结果(不执行计算)。由于结果是相同的数组(不是具有相似值的新数组),因此将通过areMergedPropsEqualareStatePropsEqual检查(除非发生其他更改)。

Reselect是一个帮助您创建记忆选择器的库。

这就是为资产创建备忘选择器的方法。 ids(未经测试):

areMergedPropsEqual