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

RTK Query中updateCachedData的draft参数push方法报错问题

问题根因

draft.push报类型错误+运行时错误,核心原因是RTK Query无法推断当前endpoint缓存值的类型,且实际缓存的根数据并不是你以为的数组类型,通常由以下几种错误写法触发:

  • 定义builder.query时未传入正确的泛型参数,TS无法推导缓存数据结构,将draft识别为void/any
  • 接口返回值是带外层包装的对象(如{code:0, data: []}),未配置transformResponse拆解出目标数组,导致缓存里存的是整个对象而非数组,自然不存在push方法
  • 误将onCacheEntryAdded配置在了mutation类型的endpoint上,mutation无长期持久化的缓存条目,updateCachedData无法拿到有效的可修改草稿
  • 缓存根数据是对象(如分页结构{list: [], total: number}),直接在根draft上调用push,没有定位到实际的数组字段
修复方案

1. 给query endpoint显式声明类型,配置正确的响应转换

以消息列表实时更新场景为例,正确的endpoint写法如下:

// 先定义单条消息的类型
type ChatMessage = {
  id: string
  content: string
  userId: string
  createTime: number
}

export const apiSlice = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({ baseUrl: 'http://localhost:5994' }),
  endpoints: (builder) => ({
    // 重点:builder.query传入两个泛型参数,第一个为缓存最终存储的类型,第二个为查询入参类型
    getMessageList: builder.query<ChatMessage[], void>({
      query: () => '/api/messages',
      // 如果接口返回带外层包装,必须通过transformResponse拆解出目标数组,和泛型声明的类型对齐
      transformResponse: (rawRes: { code: number; data: ChatMessage[] }) => rawRes.data,
      async onCacheEntryAdded(arg, { updateCachedData, cacheDataLoaded, cacheEntryRemoved }) {
        const ws = new WebSocket("ws://localhost:5994/ws");
        try {
          // 等待初始查询完成,缓存条目存在后再绑定消息监听
          await cacheDataLoaded;

          const listener = (event: MessageEvent) => {
            const newMessage = JSON.parse(event.data) as ChatMessage;
            updateCachedData((draft) => {
              // 此处TS会自动推断draft为ChatMessage[]类型,无类型错误
              draft.push(newMessage);
            });
          };

          ws.addEventListener("message", listener);
        } catch {
          // 可在此补充ws连接失败的重连逻辑
        }

        // 缓存条目移除时主动关闭ws连接,避免内存泄漏
        await cacheEntryRemoved;
        ws.close();
      },
    })
  })
})

2. 针对性排查

  • 若使用分页结构,缓存类型声明为{list: ChatMessage[], total: number}时,更新逻辑要改为draft.list.push(newMessage)
  • 不要在mutation上使用onCacheEntryAdded做缓存更新,mutation的缓存不会被持久化,生命周期触发逻辑不符合预期
  • 不要用as any强行绕过类型检查,优先对齐泛型声明、transformResponse返回值、实际更新逻辑三者的数据结构
同类写法正常运行的原因

其他开发者的代码中,要么显式传入了query的泛型参数,要么TS可以从query返回值、transformResponse返回值自动推导出缓存值的正确类型,运行时缓存的根数据确实是数组实例,因此不会触发类型和运行时错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:45:37