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

如何正确使用createSelector缓存遍历对象的Redux选择器?

Redux选择器缓存问题解决方法

我写了这样一个Redux选择器:

const selectListOfApplicationIdAndApplicationCompany =
  state => Object.values(state.applications.dict)
    .map((x) => ({
      "id": x.id,
      "companyName": x.companyName
    })
  );

React提示这个选择器需要缓存,因为相同输入参数会返回不同的对象。我理解原因,但看了Redux的createSelector文档还是不知道怎么正确缓存它。

我试了下面的写法:

export const selectListOfApplicationIdAndApplicationCompany = createSelector(
  [_selectListOfApplicationIdAndApplicationCompany],
  (data) => data
);

结果收到警告:

The result function returned its own inputs without modification. e.g
createSelector([state => state.todos], todos => todos) This could
lead to inefficient memoization and unnecessary re-renders. Ensure
transformation logic is in the result function, and extraction logic
is in the input selectors.

文档提到「输入选择器」和「输出选择器」,但我搞不清原选择器哪部分属于输入、哪部分属于输出,也不确定能不能拆分。


正确的缓存写法

要解决这个问题,核心是把选择器拆成明确的两部分:

  • 输入选择器:只负责从state里提取原始的、未加工的数据,这里就是state.applications.dict这个字典对象
  • 结果函数:负责把原始数据转换成你需要的结构(也就是原来的Object.values遍历+map转换逻辑)

这样createSelector会自动缓存结果函数的返回值:只有当输入选择器提取的原始字典引用发生变化时,才会重新执行转换逻辑;否则直接返回缓存的结果对象,避免每次调用都生成新数组/新对象,从而解决重复渲染问题。

正确代码如下:

import { createSelector } from '@reduxjs/toolkit'

// 输入选择器:提取原始的applications字典
const selectApplicationsDict = state => state.applications.dict

// 带缓存的目标选择器
export const selectListOfApplicationIdAndApplicationCompany = createSelector(
  [selectApplicationsDict], // 传入输入选择器数组
  (applicationsDict) => {
    // 结果函数:在这里完成数据转换
    return Object.values(applicationsDict).map(x => ({
      id: x.id,
      companyName: x.companyName
    }))
  }
)

为什么之前的写法会触发警告

你之前的写法是把已经完成转换的新数组作为输入选择器的返回值,然后结果函数直接返回这个输入。这种情况下,输入选择器每次调用都会生成新数组(map必然返回新引用),createSelector会判定输入每次都变化,缓存完全起不到作用,所以才会提示你要把「数据提取逻辑」放在输入选择器,「数据转换逻辑」放在结果函数里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 08:30:00