You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Reselect选择器记忆化中对象输入的缓存有效性疑问

Reselect选择器记忆化的常见疑问解答

Redux官网发布了一篇关于使用Reselect库实现选择器记忆化的文章,文中给出如下示例代码:

const state = {
  a: {
    first: 5
  },
  b: 10
}

const selectA = state => state.a
const selectB = state => state.b

const selectA1 = createSelector([selectA], a => a.first)

const selectResult = createSelector([selectA1, selectB], (a1, b) => {
  console.log('Output selector running')
  return a1 + b
})

const result = selectResult(state)
// Log: "Output selector running"
console.log(result)
// 15

const secondResult = selectResult(state)
// No log output
console.log(secondResult)
// 15

该示例整体易懂,但存在一个疑问:Redux文档指出:

当调用选择器时,Reselect会运行所有传入的输入选择器,检查返回值。若任意结果与之前的结果不全等(===),则会重新运行输出选择器,并将这些结果作为参数传入。

那如果给selectA1提供state.a这类对象作为输入选择器的返回值,是否会每次都无法通过===检查,导致a => a.first函数每次都执行?


你的理解有偏差,核心在于对象的全等检查是基于引用的:

  • 在示例中,两次调用selectResult传入的是同一个state对象,state.a的引用完全没有变化。因此selectA返回的对象引用和上一次调用时的返回值是全等的(===成立)。
  • Reselect检测到输入选择器的返回值没有变化,就会直接返回selectA1之前缓存的结果(也就是5),不会重新执行a => a.first这个函数。

只有当state.a的引用发生改变时(比如通过state.a = {first: 5}这种方式替换成新对象),selectA的返回值才会和之前的缓存值不全等,这时候selectA1才会重新执行输出函数计算新的结果。

额外补充:如果只是修改state.a内部的属性(比如state.a.first = 6),但state.a的引用没变化,Reselect会认为输入没有改变,selectA1会继续返回旧的缓存值,这也是为什么在Redux中推荐使用不可变更新方式的原因之一——确保对象引用变化能被Reselect检测到。

内容的提问来源于stack exchange,提问作者Natsuo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:42:32