首页 > 解决方案 > 我们可以为每个选择器(即使是最简单的 getter)使用带有 redux 的 Reselect memoization 吗?

问题描述

我是 Redux 的新手,我一直在阅读关于它的好东西,包括记忆技术(尤其是重新选择)。我有一个问题,但我很难找到正确的答案。如果我们为每个单独的选择器添加记忆(假设我们有很多),即使是简单的 getter,它会导致性能问题(可能是由于引擎盖下的记忆数据?)?复杂选择器的记忆显然是有益的,因为它可以防止在不需要时重新计算。但我发现简单选择器的记忆化也是有益的,以避免无用的重新渲染。

事实上,我使用 useSelector 钩子和文档状态:

当一个动作被调度时, useSelector() 将对先前的选择器结果值和当前结果值进行参考比较。如果它们不同,组件将被强制重新渲染。如果它们相同,则组件不会重新渲染。

因此,即使选择器返回相同的原始值(比如一个 int),如果我没记错,useSelector 应该总是让组件重新渲染(即使选择器总是返回相同的值)。

如果我说的是真的,那么记住即使是简单的 getter 也是有用的,但是过度使用它会导致其他性能问题吗?

感谢您的帮助

标签: reactjsreduxreselect

解决方案


编写 memoized selector 函数很有用,但是很多人试图 memoize太多实际上不应该 memoized的选择器。

如果选择器函数只是从状态中进行简单的查找和返回现有数据,则无需记忆它——它可能只是一个简单的函数。例如:

const selectTodoById = (state, id) => state.todos.entities[id];

其次,您可能也不应该为每个状态字段创建单独的选择器。找到合理的粒度级别。

Memoized 选择器仅在选择器返回一些派生数据时才有用。一个很好的例子是过滤数组:

const selectCompletedTodos = createSelector(
  state => state.todos,
  state => state.filters.completed,
  (todos, completed) => todos.filter(t => t.completed === completed)
);

这样,只有当输入值发生变化时,才会重新计算派生数据。

作为旁注,我实际上计划编写一个新的 Redux 核心文档页面,其中包含有关何时以及如何编写记忆选择器的指导和使用信息。在此之前,您可以阅读我的文章Using Reselect Selectors for Encapsulation and Performance,其中已经涵盖了很多相关材料。


推荐阅读