通过同时使用一个记忆选择器和一个相等比较函数,对“ useSelector”有什么性能上的好处?

时间:2020-06-22 17:27:01

标签: reactjs redux reselect

我的列表组件具有以下逻辑:

const List = React.memo(() => {
    const apples = useSelector(
        (state) => Object.values(state.apples),
        (currentState, prevState) => currentState.length === prevState.length,
    );

  return 'whatever';
);

这在渲染时间方面给了我很好的结果->它仅渲染一次,并且仅在“苹果”的长度发生变化时才重新渲染,而在苹果的属性发生变化时则不渲染。

但是,我想知道添加memoized selector是否会带来任何性能上的好处?

为说明我的示例:

const applesSelector = createSelector(
    (state) => Object.values(state.apples)
)

const List = React.memo(() => {
    const apples = useSelector(
        applesSelector,
        (currentState, prevState) => currentState.length === prevState.length,
    );

  return 'whatever';
);

因此,我很难发现useSelector可以通过同时使用一个记忆选择器和一个相等比较函数来获得性能上的好处?

2 个答案:

答案 0 :(得分:3)

首先,applesSelector的示例实现似乎有错误。正确的实现是:

const applesSelector = createSelector(
  state => state.apples,
  apples => Object.values(apples)
)

这样,输出选择器实际上仅在state.apples更改时运行。

对于您的实际问题:如果您使用的是记忆选择器,通常不需要在useSelector中添加一个相等比较参数,因为进行比较的工作已经在内部进行了。选择器功能。

答案 1 :(得分:1)

记忆化是重新选择的不错选择,但您获得的主要好处是可组合选择器。与其在1个选择器中回答2个问题(苹果在哪里,我以什么形状返回它们),您可以在一个选择器中回答一个问题:selectAppes中的“苹果在哪里”和“我以什么形状返回它们”作为selectApplesAsArray使用selectApples获取苹果。这样可以防止重复执行。

apples示例有些简单,但是React应用程序在您不想重复的选择器中可以具有复杂的业务规则。诸如selectPolicyPrice之类的东西可能需要重新使用其他选择器,以防止重复执行,当政策定价规则更改时,重复执行会导致难以修复的错误。

有时您可能想记住数组结果,例如当您执行Object.keys,Object.values或Array.prototype.filter时。

const { createSelector, defaultMemoize } = Reselect;

const createMemArray = () => {
  const memArr = defaultMemoize((...arr) => arr);
  return (arr) => memArr(...arr);
};
const selectApples = (state) => state.apples;
const selectApplesAsArray = ((
  mem //mem will memoize array
) =>
  createSelector([selectApples], (apples) =>
    mem(Object.values(apples))//memoize each item in apples
  ))(createMemArray()); //IIFE createing memoized array

const state = { apples: { a: 1, b: 2 } };
const a = selectApplesAsArray(state),
  b = selectApplesAsArray({
    ...state,
    //copied, will not recalculate because of memoize array
    apples:{...state.apples},
    irrelevantChange: 22,
  });
console.log('a is b:', a === b);
console.log('a and b are:', a);
const c = selectApplesAsArray({
  ...state,
  apples: { ...state.apples, b: 'changed' },
});
console.log('c is b:', c === b);
console.log('c is:', c);
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>


<div id="root"></div>

我写了一些short examples,如何将选择器与redux一起使用,这可能会有所帮助。