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

如何在Redux reducer合并event对象时实现dates数组的合并去重

实现方案

你当前的reducer用了Immer的draft可变模式,只需调整reduce回调中对event对象的构造逻辑,单独处理dates字段的合并去重即可,完整代码如下:

case LOAD_SUCCESS:
  draft.loading = false;
  draft.events = {
    ...state.events,
    ...action.events.reduce((acc, newEvent) => {
      // 取同id的旧事件数据,不存在则默认空对象
      const existedEvent = state.events[newEvent.id] || {};
      // 合并新旧dates后去重,start和end都一致则视为重复项
      const mergedDates = [...(existedEvent.dates || []), ...newEvent.dates].filter(
        (date, idx, arr) => idx === arr.findIndex(item => item.start === date.start && item.end === date.end)
      );
      // 其他字段用新拉取的版本,仅dates用合并去重后的结果
      return {
        ...acc,
        [newEvent.id]: {
          ...newEvent,
          dates: mergedDates
        }
      };
    }, {})
  };
  break;

逻辑说明

  • 优先从现有状态中读取同id的旧event数据,避免新增event时报错
  • 合并dates数组时对旧数据做兜底处理,无旧数据时默认是空数组
  • 去重逻辑通过findIndex匹配相同start、end的项,仅保留第一个匹配项实现去重
  • 构造最终event对象时先展开新拉取的所有字段,再覆盖dates为合并结果,保证除dates外所有字段都是最新的后端值

性能优化(可选)

如果你的event数据量或dates数组长度较大,可以用Map做标记实现O(n)时间复杂度的去重,替换上方的filter去重逻辑即可:

const dateMarker = new Map();
// 先后添加旧、新dates,重复项会自动被后续同key值覆盖
[...(existedEvent.dates || []), ...newEvent.dates].forEach(date => {
  const uniqueKey = `${date.start}|${date.end}`;
  dateMarker.set(uniqueKey, date);
});
const mergedDates = Array.from(dateMarker.values());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 20:45:07