React Query乐观更新报错‘old is not iterable’的原因及修复方法
修复React Query乐观更新的‘old is not iterable’错误
错误根源拆解
- 数据结构不匹配:个人资料是单个对象而非数组,代码里用
[...old, newProfile]尝试把对象当数组展开,触发old is not iterable错误。 - 查询Key不一致:
cancelQueries和getQueryData用的是字符串"user-profile",但setQueryData用的是数组["user-profile"],React Query会将这两个判定为不同查询Key,导致无法正确读取旧数据。 - 上下文变量名错误:
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
相关产品推荐
相关产品推荐

