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

如何用Reselect选择器避免Redux Store高频变动属性触发重计算

解决方案

方案1:自定义Selector比较逻辑(改造成本最低)

reselect默认使用引用相等判断输入是否变化,你可以通过自定义比较规则忽略position字段的变动,不需要修改原有Store结构和业务逻辑:

import { createSelectorCreator, defaultMemoize } from 'reselect'
import isEqualWith from 'lodash/isEqualWith'

// 自定义相等判断:所有字段都相等才算相等,position字段直接判定为相等
const ignorePositionComparer = (prevVal, nextVal) => {
  return isEqualWith(prevVal, nextVal, (a, b, key) => {
    if (key === 'position') return true
  })
}

// 生成带自定义比较规则的selector创建器
const createCustomSelector = createSelectorCreator(
  defaultMemoize,
  ignorePositionComparer
)

// 直接替换原有createSelector即可
const getSelectedItems = createCustomSelector(
  getAllItems,
  getSelectedItemsKeys,
  (allItems, selectedKeys) => allItems.subset(selectedKeys)
)

如果不想引入lodash,也可以自己实现对应字段的比较逻辑,只检查你关心的uivalue1、uivalue2等UI字段是否变化即可。

方案2:拆分输入选择器,仅依赖UI相关字段

从根源上避免把包含position的完整allItems作为输入依赖,只提取你需要的UI字段作为selector的输入源:

// 提取单个item的UI相关数据,完全不包含position
const getSelectedItemsUiData = createSelector(
  getAllItems,
  getSelectedItemsKeys,
  (allItems, keys) => keys.map(key => ({
    key,
    uivalue1: allItems[key].uivalue1,
    uivalue2: allItems[key].uivalue2
  }))
)

// 后续UI组件直接依赖这个selector即可,position变动不会触发它重新计算
const getSelectedItemsForUi = createSelector(
  getSelectedItemsUiData,
  (uiDataList) => uiDataList
)

如果你的组件只用到UI字段,直接用这个selector返回的结果就行,不需要拿完整的item数据。

方案3:修复re-reselect的使用逻辑

你之前的用法确实是对re-reselect的理解有偏差:它的缓存key仅用于多实例缓存,只要输入选择器的返回值发生变化,不管缓存key是否相同,都会重新执行计算逻辑。如果要继续用re-reselect,需要增加一个和position无关的hash输入:

// 生成仅和UI字段相关的哈希,position变动不会改变哈希值
const getSelectedItemsUiHash = createSelector(
  getAllItems,
  getSelectedItemsKeys,
  (allItems, keys) => keys.map(key => 
    `${key}_${allItems[key].uivalue1}_${allItems[key].uivalue2}`
  ).join('|')
)

const getSelectedItems = createCachedSelector(
  getSelectedItemsUiHash,
  getSelectedItemsKeys,
  getAllItems,
  (hash, keys, allItems) => allItems.subset(keys)
)(
  (state) => `keys-${state.selectedItemsKeys.join(':')}`
)

这样只有getSelectedItemsUiHash返回的哈希值变化时,才会重新执行subset计算,position变动不会触发重计算。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:57:04