我有一个普通的选择器,它只是用来获得状态的一部分:
export const getAllPosts = state => {
return state.posts;
};
如果我使用重新选择来包裹选择器:
import { createSelector } from 'reselect';
export const allPosts = createSelector(
getAllPosts,
(posts) => posts
);
提高性能是否有任何意义?在我看来,包装是不必要的。
答案 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])
);
现在你的选择器变成了性能提升,因为它只会在商店中的某些东西发生变化时计算派生数据。
所以我的经验法则是:如果你没有得到数据,你就不需要记住它。