【问题标题】:Reselect - does it ever make sense to create a memorized selector which is just used to get part of the state?重新选择 - 创建一个仅用于获取部分状态的记忆选择器是否有意义?
【发布时间】:2017-11-07 10:41:18
【问题描述】:

我有一个普通的选择器,它只是用来获取状态的一部分:

export const getAllPosts = state => {
  return state.posts;
};

如果我使用重新选择来包装选择器:

import { createSelector } from 'reselect';

export const allPosts = createSelector(
  getAllPosts,
  (posts) => posts
);

提高性能是否有意义?在我看来,包装是不必要的。

【问题讨论】:

  • 好问题 - 我在任何地方都找不到这个问题。

标签: redux reselect


【解决方案1】:

不,仅仅为了获取状态树的一部分而创建一个记忆选择器是没有意义的。

原因是connect 将对从mapStateToProps 传入的每个道具进行自己的浅层相等检查。如果选择器返回的道具与其他道具一起通过了浅层相等检查,那么render 将不会被不必要地调用。如果选择器只是返回了状态树的一部分并且状态树的那部分没有被修改,那么浅的相等检查就足够了。

但是,如果选择器是从其他选择器的结果中计算出来的,那么使用createSelector 是一个不错的选择。首先,它为组合选择器提供了一种很好的语法。其次,如果组合选择器的计算可能很昂贵,您将获得性能优势。第三,如果选择器要返回一个新的但等效的对象或数组,那么 connect 提供的浅层相等性检查是不够的。在这种情况下,createSelector 提供的记忆将确保在输入未更改的情况下返回相同的对象或数组实例,然后浅层相等性检查足以避免代价高昂的重新渲染。

因此,仅公开状态树的部分createSelector 不会添加任何内容。

对于从状态树的多个部分计算的几乎所有选择器createSelector 开始增加价值。它添加的价值量因选择器而异,从更容易阅读到确保您不会不必要地重新渲染组件树。

【讨论】:

    【解决方案2】:

    在您的情况下,这没有任何意义,因为您只需从存储中返回相同的引用,该引用始终浅等于自身(或它的先前状态),除非您对其进行修改。

    如果您设想一个不同的场景,例如您将实体存储在对象中而不是存储中的数组中,但您想将数组返回给组件,那么您需要派生数据:

    export const selectAllPosts = createSelector(
      getAllPostsFromStore, // returns { 1: {...}, 2: {...} }
      (allPosts) => Object.keys(allPosts).map(key => allPosts[key])
    );
    

    现在您的选择器变成了性能提升,因为它只在商店中的某些内容发生变化时计算派生数据。

    所以我的经验法则是:如果你不派生数据,你就不需要记忆它。

    【讨论】:

      【解决方案3】:

      不,这并没有真正的好处。

      我发现我的第一级选择器只是简单的函数,任何比这更深的选择器都需要记忆:

      // assume state is:  {first : {second {} } }
      
      const selectFirst = state => state.first;
      
      const selectSecond = createSelector(
          selectFirst,
          first => first.second
      );
      

      【讨论】:

      • 为什么要记住selectSecond?我看不到明显的性能改进。能多解释一下吗?
      • 这个例子很简单。但是,假设selectSecond() 的输出选择器正在做一些昂贵的工作(可能对数组进行排序/过滤),而我们只想在数组发生变化时这样做。使用createSelector() 并记忆输入将确保输出选择器仅在输入更改时运行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-30
      • 1970-01-01
      • 1970-01-01
      • 2020-08-06
      • 2012-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多