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

Next.js中React Query配置缓存后仍重复调用API问题

解决方案:Next.js getServerSideProps + React Query 重复调用API问题

核心原因

React Query的默认缓存是客户端内存级缓存,而getServerSideProps每次请求都会在服务端独立执行,服务端的查询上下文和客户端完全隔离,所以即使设置了cacheTime和staleTime,服务端渲染阶段仍会触发API调用;如果客户端接管后配置不当,还可能再触发一次重复请求。


1. 服务端预取数据,客户端复用缓存(最优方案)

利用getServerSideProps在服务端提前获取数据,通过initialData传给React Query初始化缓存,彻底避免重复请求:

页面组件代码

import { useGetPolicyPage } from '../hooks/useGetPolicyPage';

// 服务端预取数据
export async function getServerSideProps() {
  // 和useGetPolicyPage里的API逻辑保持一致
  const res = await fetch('https://your-api-domain/refund-policy');
  const initialPolicyData = await res.json();

  return { props: { initialPolicyData } };
}

export default function RefundPolicyPage({ initialPolicyData }) {
  // 用服务端预取的数据初始化React Query缓存
  const { data } = useGetPolicyPage({
    initialData: initialPolicyData,
    staleTime: 86400000, // 1天内数据视为新鲜
    cacheTime: 86400000, // 缓存保留1天
  });

  return <div className="policy-content">{data.content}</div>;
}

自定义钩子适配initialData

// hooks/useGetPolicyPage.js
import { useQuery } from '@tanstack/react-query';

export function useGetPolicyPage({ initialData, ...options }) {
  return useQuery({
    queryKey: ['refund-policy'], // 固定查询键,确保缓存命中
    queryFn: async () => {
      const res = await fetch('https://your-api-domain/refund-policy');
      if (!res.ok) throw new Error('Failed to fetch policy');
      return res.json();
    },
    initialData,
    ...options,
  });
}

2. 排查缓存键(queryKey)问题

确保queryKey是固定值(比如['refund-policy']),不要动态生成无意义的变量。如果每次渲染queryKey都不同,React Query会认为是新查询,直接跳过缓存发起请求。


3. 禁用服务端查询(适合非SEO敏感页面)

如果退款政策不需要服务端渲染(比如纯静态内容),可以让React Query仅在客户端执行:

export default function RefundPolicyPage() {
  const { data } = useGetPolicyPage({
    enabled: typeof window !== 'undefined', // 仅在浏览器环境启用查询
    staleTime: 86400000,
    cacheTime: 86400000,
  });

  // 服务端渲染时显示占位内容
  if (!data) return <div>Loading refund policy...</div>;

  return <div className="policy-content">{data.content}</div>;
}

4. 检查全局React Query配置

确保_app.js中的Provider没有强制全局刷新的配置,避免覆盖单个查询的staleTime:

// _app.js
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      refetchOnMount: false, // 禁止挂载时强制刷新
      refetchOnWindowFocus: false, // 禁止窗口聚焦时刷新
      staleTime: 3600000, // 全局默认新鲜时间(可选)
    },
  },
});

function MyApp({ Component, pageProps }) {
  return (
    <QueryClientProvider client={queryClient}>
      <Component {...pageProps} />
    </QueryClientProvider>
  );
}

export default MyApp;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 18:22:17