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

Redux reducer处理action时如何同时执行set与push更新状态

不需要拆分两次action触发更新

完全没必要用saga拆分payload分两次dispatch,Immutable的状态更新支持链式调用,完全可以在单次reducer执行中完成所有更新操作后再返回最终状态。拆分两次dispatch反而会产生中间态,让订阅store的组件拿到不完整的数据触发错误渲染,属于冗余设计。

你当前代码的几个明显问题

  • 循环逻辑冗余:遍历单个node的过程中反复对全量nodes做filter,时间复杂度高,没有必要
  • 存在性判断错误:findIndex未找到匹配项时返回-1,属于JS真值,你当前的过滤逻辑会把不存在的节点也归到setNodes里,结果完全不符合预期
  • 提前return中断逻辑:只要命中setNodes分支就直接返回状态,后续所有待更新、待新增的节点都不会被处理
  • API使用错误:Immutable List的push会把传入参数作为单个元素追加,你直接传入pushNodes数组会导致状态里出现嵌套结构;代码中用到的index变量没有定义,运行会直接报错

正确实现代码

先构建id到索引的映射避免反复遍历原状态,再逐个处理节点,最后统一追加新节点即可:

case 'MODIFY_NODES': {
  const { nodes } = action.payload;
  if (!nodes?.length) return state;

  // 构建id-索引映射,O(n)时间完成存在性判断,避免反复遍历state
  const idIndexMap = new Map();
  state.forEach((item, index) => {
    idIndexMap.set(item.get('id'), index);
  });

  let nextState = state;
  const pendingAdd = [];

  for (const node of nodes) {
    const nodeId = node.id;
    if (idIndexMap.has(nodeId)) {
      // 已存在节点直接更新对应位置
      nextState = nextState.set(idIndexMap.get(nodeId), fromJS(node, toImmutableFunction));
    } else {
      // 不存在的节点先暂存,最后统一追加
      pendingAdd.push(fromJS(node, toImmutableFunction));
    }
  }

  // 批量追加所有新节点
  return pendingAdd.length ? nextState.concat(pendingAdd) : nextState;
}

这个实现只需要遍历一次原state、一次传入的nodes数组,没有冗余计算,也不会产生中间状态,单次返回最终结果即可满足需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:24:28