跳到主要内容

开始使用 Reselect

一个用于创建 memoized "selector" 函数的库。常与 Redux 一起使用,但也可以与任何普通的 JS 不可变数据一起使用。

  • Selectors 可以计算派生数据,允许 Redux 存储最小可能的状态。
  • Selectors 是高效的。除非其中一个参数发生变化,否则不会重新计算 selector。
  • Selectors 是可组合的。它们可以作为其他 selectors 的输入。

Redux 文档的 使用 Selectors 派生数据 页面涵盖了 selectors 的目的和动机,为什么 memoized selectors 是有用的,典型的 Reselect 使用模式,以及如何与 React-Redux 一起使用 selectors。

安装

Redux Toolkit

虽然 Reselect 不仅限于 Redux,但它已经默认包含在 官方的 Redux Toolkit 包 中 - 无需进一步安装。

import { createSelector } from '@reduxjs/toolkit'

独立使用

对于独立使用,安装 reselect 包:

npm install reselect

基本使用

Reselect 导出了一个 createSelector API,用于生成 memoized selector 函数。createSelector 接受一个或多个输入 selectors,这些 selectors 从参数中提取值,以及一个结果函数,该函数接收提取的值并应返回一个派生值。如果多次调用生成的输出 selector,只有在提取的值发生变化时,输出才会被重新计算。

你可以在以下 示例 中尝试 这个 CodeSandbox

basicUsage.ts
import { createSelector } from 'reselect'

interface RootState {
todos: { id: number; completed: boolean }[]
alerts: { id: number; read: boolean }[]
}

const state: RootState = {
todos: [
{ id: 0, completed: false },
{ id: 1, completed: true }
],
alerts: [
{ id: 0, read: false },
{ id: 1, read: true }
]
}

const selectCompletedTodos = (state: RootState) => {
console.log('selector ran')
return state.todos.filter(todo => todo.completed === true)
}

selectCompletedTodos(state) // 选择器运行
selectCompletedTodos(state) // 选择器运行
selectCompletedTodos(state) // 选择器运行

const memoizedSelectCompletedTodos = createSelector(
[(state: RootState) => state.todos],
todos => {
console.log('记忆选择器运行')
return todos.filter(todo => todo.completed === true)
}
)

memoizedSelectCompletedTodos(state) // 运行了记忆化的选择器
memoizedSelectCompletedTodos(state)
memoizedSelectCompletedTodos(state)

console.log(selectCompletedTodos(state) === selectCompletedTodos(state)) //=> false

console.log(
memoizedSelectCompletedTodos(state) === memoizedSelectCompletedTodos(state)
) //=> true

如上例所示,memoizedSelectCompletedTodos 在第二次或第三次运行时不会运行,但我们仍然得到与上次相同的返回值。

除了跳过不必要的重新计算,memoizedSelectCompletedTodos 如果没有重新计算,将返回现有的结果引用。这对于像 React-Redux 或 React 这样经常依赖引用相等性检查来优化 UI 更新的库来说非常重要。


术语

下面的例子可以作为一个视觉辅助:

const outputSelector = createSelector(
[inputSelector1, inputSelector2, inputSelector3], // 与 `依赖项` 同义。
resultFunc // 结果函数
)