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

如何让useCallback与Redux-Toolkit createSelector记忆化正常生效?

问题根源

你的代码记忆化不生效的核心错误是:useCallback(selectSum, []) 只是缓存了全局导入的同一个selectSum引用,两个Sum组件实例调用的始终是全局共享的同一个selector。
当两个组件分别传入value=1、value=2调用同一个selector时,selector每次收到的第二个参数都在两个值之间来回切换,永远无法命中记忆缓存,因此每次重渲染都会触发两次重新计算、打印两次日志。

修复方法

官方文档要求的「每个组件创建独立selector实例」,指的是每个组件实例需要拥有专属的全新记忆化selector,而非复用全局唯一的selector。具体修改分两步:

  • 第一步:把全局导出的固定selector,改成可以生成新selector实例的工厂函数
  • 第二步:在组件内通过useMemo调用工厂函数,为当前组件生成专属selector,不要用useCallback包裹全局selector

修改reducer侧的selector定义

// 移除原来全局固定的selectSum导出
// export const selectSum = createSelector(...)

// 改为导出selector工厂函数,每次调用都会返回独立的新selector实例
export const makeSelectSum = () => createSelector(
  [state => state.baseNum, (_, addNum) => addNum],
  (baseNum, addNum) => {
    console.log('触发sum计算')
    return baseNum + 100 + addNum
  }
)

修改组件侧的调用逻辑

import { useMemo } from "react";
import { useSelector, useDispatch } from "react-redux";
import { increment, makeSelectSum } from "./reducer";

function Sum({ value }) {
  // 给当前组件实例生成独一份的selector,组件挂载到卸载期间引用不变
  const selectSumForThisInstance = useMemo(makeSelectSum, []);
  // 调用专属selector传参,每个组件的selector只会收到固定的value值
  const sum = useSelector(state => selectSumForThisInstance(state, value));
  
  return (
    <div>
      sum: {sum} (10+100+{value})
    </div>
  );
}

export default function App() {
  const dispatch = useDispatch();
  return (
    <div>
      <Sum value={1} />
      <Sum value={2} />
      <button onClick={() => dispatch(increment())}>
        change state and re-render
      </button>
    </div>
  );
}
修复后的效果
  • 首次页面加载:两个组件各自初始化自己的selector,各计算一次,共打印2次计算日志
  • 后续点击按钮触发重渲染:只要两个组件的value prop不发生变化,两个selector都会命中缓存,不会触发重新计算,没有额外日志输出
  • 如果某个组件的value prop更新:只会触发对应组件自身的selector重新计算,不会干扰其他组件的缓存结果

注意:useCallback只能缓存已有函数的引用,不会创建新的selector实例,所以用它包裹全局selector完全达不到「每个组件独立实例」的要求,必须用工厂函数配合useMemo生成新实例才行。

内容的提问来源于stack exchange,提问作者Chong Lip Phang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 11:33:21