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

React Query乐观更新报错‘old is not iterable’的原因及修复方法

修复React Query乐观更新的‘old is not iterable’错误

错误根源拆解

  1. 数据结构不匹配:个人资料是单个对象而非数组,代码里用[...old, newProfile]尝试把对象当数组展开,触发old is not iterable错误。
  2. 查询Key不一致:cancelQueries和getQueryData用的是字符串"user-profile",但setQueryData用的是数组["user-profile"],React Query会将这两个判定为不同查询Key,导致无法正确读取旧数据。
  3. 上下文变量名错误:onMutate里返回的是previousTodos,但实际定义的变量是previousProfile,导致onError回滚时找不到正确的旧数据。

修复后的完整代码

export const useUpdateProfile = () => {
  const queryClient = useQueryClient();
  // 统一查询Key,避免前后不一致
  const profileQueryKey = "user-profile";

  return useMutation(updateProfile, {
    onMutate: async (newProfile) => {
      await queryClient.cancelQueries(profileQueryKey);
      const previousProfile = queryClient.getQueryData(profileQueryKey);

      // 针对单个对象的乐观更新,用对象合并替换数组展开
      queryClient.setQueryData(profileQueryKey, (old) => ({
        ...old,
        ...newProfile
      }));

      // 返回正确的上下文变量
      return { previousProfile };
    },
    onError: (err, newProfile, context) => {
      // 增加空值判断,避免旧数据不存在时出错
      if (context?.previousProfile) {
        queryClient.setQueryData(profileQueryKey, context.previousProfile);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries(profileQueryKey);
    },
  });
};

核心修复点说明

  • 统一查询Key:将查询Key定义为常量,确保所有操作指向同一个查询,避免React Query无法定位目标数据。
  • 适配对象更新逻辑:个人资料是单个对象,使用{...old, ...newProfile}合并新旧属性,而非数组展开语法。
  • 修正上下文变量名:onMutate返回正确的previousProfile,确保onError能正常回滚数据。
  • 增加空值防护:在回滚时判断旧数据是否存在,避免额外报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 00:06:26