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

Redux中在reducer内做深度比较、无变更时返回原状态是否为常见实践?

结论

你提到的「reducer中先深度比较内容,无变更则返回原state」的做法是非常通用的前端状态管理优化实践,完全符合Redux的设计规范,针对你描述的定期拉取、多数时候数据无变化的场景适配性很高。

原写法的问题

直接返回新state的写法是Redux的基础入门写法,只满足了不可变更新的最低要求,没有考虑冗余更新的性能损耗,在高频更新、重复数据多的场景下确实会导致createSelector缓存失效、衍生计算逻辑重复执行,甚至触发下游组件不必要的重渲染,属于典型的可优化场景。

不同场景的可选优化方案

你提到的深度比较方案是可行的,除此之外还有其他适配不同场景的方案可以选择:

  • 数据量小的场景:直接在reducer中用成熟的深比较函数(比如lodash.isEqual)对比新旧数组,内容一致就返回原state,深比较的开销远低于后续冗余计算、重渲染的开销,性价比很高。
    示例代码:
    import isEqual from 'lodash/isEqual'
    
    // reducer逻辑
    if (isEqual(state.arrayOfData, fetchedArrayOfData)) {
      return state
    }
    return {
      ...state,
      arrayOfData: fetchedArrayOfData,
    }
    
  • 数据量大的场景:深比较本身会产生较高开销,可以让接口返回数据的同时携带内容哈希/ETag标识,前端拉取到数据后先对比标识,标识一致就直接不更新state,比深比较性能高很多。
  • 不想修改reducer逻辑的场景:可以修改createSelector的比较逻辑,使用自定义的深比较比较器替代默认的浅比较,同样可以实现缓存不失效,示例如下:
    import { createSelectorCreator, defaultMemoize } from 'reselect'
    import isEqual from 'lodash/isEqual'
    
    // 创建一个支持深比较的selector构造器
    const createDeepEqualSelector = createSelectorCreator(
      defaultMemoize,
      isEqual
    )
    
    // 用这个构造器创建你的selector即可
    const yourSelector = createDeepEqualSelector(
      state => state.arrayOfData,
      (arrayOfData) => {
        // 你的转换逻辑,只有arrayOfData内容真的变化时才会执行
      }
    )
    
  • 有条件的话也可以直接使用RTK Query、SWR这类封装好的请求工具,这类工具默认自带响应缓存能力,接口返回内容无变化的话根本不会触发状态更新,从根源上避免了这个问题。

注意事项

不要无差别给所有reducer都加深比较逻辑,对于确定每次更新数据都会变化的场景,加深比较只会多一层不必要的开销,反而会降低性能。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 04:15:02