重新选择 - 创建一个仅用于获取状态的记忆选择器是否有意义?

时间:2017-11-07 10:41:19

标签: redux reselect

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

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

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

import { createSelector } from 'reselect';

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

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

3 个答案:

答案 0 :(得分:6)

不,创建一个memoized选择器只是为了获得状态树的一部分是没有意义的。

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

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

因此,只是暴露状态树的一部分createSelector不会添加任何内容。

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

答案 1 :(得分:0)

不,这没有任何实际好处。

我发现我的第一级选择器只是普通的功能,任何比这更深入的选择器都需要记忆:

// assume state is:  {first : {second {} } }

const selectFirst = state => state.first;

const selectSecond = createSelector(
    selectFirst,
    first => first.second
);

答案 2 :(得分:0)

在你的情况下它是没有意义的,因为你只是从商店返回相同的引用,它总是浅的等于它自己(或它以前的状态),除非你修改它。

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

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

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

所以我的经验法则是:如果你没有得到数据,你就不需要记住它。