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

Redux Toolkit中过滤对象数组缓存无效果问题求助

解决Redux Toolkit updateQueryData中数组过滤无效果的问题

你的过滤操作失效的核心原因是Immer的使用方式错误:在updateQueryData的draft回调里,你直接给draft重新赋值了(draft = draft.filter(...)),但Immer要求必须修改原draft数组本身,而不是替换整个变量引用——因为Immer是通过代理原数组来追踪变更的,重新赋值会让Immer丢失对原数组的追踪,导致你的修改不会同步到缓存中。

修复步骤

  1. 替换数组修改方式:不要直接赋值draft,而是用数组的splice方法清空原数组,再把过滤后的元素添加进去;或者直接修改原数组的内容。
  2. 修复reduce的初始值:你的reduce没有传入初始值,当reminders数组为空时会报错,需要补充符合Partial<Reminder>结构的初始值。

修改后的代码示例

combineReminders: builder.mutation<Reminder, Partial<Reminder>[]>({
  query: ([...reminders]) => ({
    url: "/",
    method: "PUT",
    body: reminders,
  }),
  async onQueryStarted([...reminders], { dispatch, queryFulfilled }) {
    const combineResult = dispatch(
      reminderApi.util.updateQueryData(
        "getReminders",
        undefined,
        (draft: Partial<Reminder>[]) => {
          const ids = reminders.map((item) => item.id);
          console.log("ids:", ids);
          // 给reduce添加初始值,避免空数组报错
          const result = reminders.reduce((acc, reminder) => {
            const { priority, date, time } = reminder;
            const compareDates = (
              date1: Date | undefined,
              date2: Date | undefined
            ) => {
              if (!date1) return date2;
              if (!date2) return date1;
              return date1 < date2 ? date2 : date1;
            };
            const compareTimes = (
              time1: string | undefined,
              time2: string | undefined
            ) => {
              if (!time1) return time2;
              if (!time2) return time1;
              return new Date(time1) < new Date(time2) ? time2 : time1;
            };
            return {
              ...acc,
              date: compareDates(date, acc.date) || date,
              time: compareTimes(time, acc.time) || time,
              priority: priority,
            };
          }, {} as Partial<Reminder>); // 补充初始值
          
          // 正确修改draft数组的方式:先清空原数组,再添加过滤后的元素
          const filtered = draft.filter(item => ids.includes(item.id));
          draft.splice(0, draft.length, ...filtered);
          // 如果需要添加合并后的result,取消下面的注释
          // draft.push(result);
          console.log(draft);
        }
      )
    );
    try {
      await queryFulfilled;
    } catch (error) {
      combineResult.undo();
    }
  },
}),

关键说明

  • Immer的draft是一个代理对象,所有修改必须直接作用于这个代理对象本身,比如用splice、push、pop等数组方法,或者修改对象的属性;不能通过重新赋值变量的方式来替换整个对象/数组。
  • 你的PUT方法和过滤逻辑无关,问题完全出在Immer的使用规范上,和HTTP方法没有关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 12:17:00