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

react-query示例中queryClient.setQueryData执行耗时过长是什么原因?

问题原因与修复方案

核心问题定位

  • queryKey未包含依赖参数:当前useQuery使用固定字符串'Style'作为查询键,没有将入参styleId、pageIndex加入queryKey,导致所有调用useStyle的实例共享同一份查询缓存,任意一个实例请求成功都会触发所有实例的onSuccess回调,大量重复执行setQueryData操作,直接导致更新阻塞。
  • initialData配置触发多余回调:配置了initialData: {},useQuery初始化时会直接使用初始值触发onSuccess,哪怕真实接口请求还未返回,相当于额外多执行一次缓存更新,多实例共存时会瞬间触发几十上百次重复更新。
  • 缓存更新逻辑未做结构优化:遍历pages时无论索引是否匹配,都返回全新的对象,导致所有page的引用全部变更,所有订阅'Styles'缓存的组件会全量重渲染,加剧性能消耗。
  • 字段拼写错误引发额外异常:更新缓存时将pageParams错误拼写为pagesParams,导致更新后分页参数丢失,可能触发额外的分页请求,进一步加剧循环更新。

修复后代码

export const useStyle = (styleId, pageIndex) => {
  const queryClient = useQueryClient();

  const { refetch } = useQuery(['Style', styleId, pageIndex], () => fetchStyle(styleId), {
    staleTime: Infinity,
    refetchOnWindowFocus: false,
    // 移除initialData配置,避免触发多余的onSuccess
    onSuccess: (res) => {
      queryClient.setQueryData('Styles', (oldData) => ({
        ...oldData, // 先展开原有数据,避免字段丢失
        pages: oldData.pages.map((page, index) => {
          // 非匹配页直接返回原引用,保留结构共享
          if (index !== pageIndex) return page
          return {
            ...page,
            Styles: {
              ...page.Styles,
              ...res.Styles,
            },
            Groups: {
              ...page.Groups,
              ...res.Groups,
            },
            Ranges: {
              ...page.Ranges,
              ...res.Ranges,
            },
          }
        }),
      }));
    },
  });

  return { refetchStyle: refetch };
};

验证方式

可以在onSuccess回调中添加日志打印,确认回调触发次数是否和预期一致,如果修复前触发次数远大于实际请求次数,即可确认是重复执行导致的性能问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 00:36:04