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

Next.js+react-query:如何实现初始数据预取且仅过滤器变更时重取?

问题分析与解决方案

问题现状

在Next.js项目中使用react-query预取数据,通过getStaticProps获取初始数据传入组件,期望页面加载时直接使用初始数据(不触发isLoading),仅在过滤器修改时重新请求数据。但当前页面加载时isLoading会先显示true,不符合预期。

相关代码如下:

组件代码

function JobSearch(props) {
  const [pageNumber, setPageNumber] = useState(1);
  const [company, setCompany] = useState("");
  const [remote, setRemote] = useState("");
  const [orderBy, setOrder] = useState("date");
  const [location, setLocation] = useState("");

  const { data: jobData, isLoading } = useQuery(
    ["jobs", pageNumber, company, remote, orderBy, location],
    () => fetchJobs(pageNumber, company, remote, orderBy, location),
    { initialData: props.jobs }
  );
  console.log(isLoading);
}

过滤器示例

<Select
  style={{ width: 200 }}
  onChange={(value) => {
    setRemote(value);
    setPageNumber(1);
  }}
  defaultValue="">
  <option value="">Qualquer</option>
  <option value="true">Remoto</option>
  <option value="false">Presencial</option>
</Select>

getStaticProps代码

export async function getStaticProps() {
  const pageNumber = 1;
  const orderBy = "date";

  jobs = await fetchJobs(pageNumber, orderBy);
  return {
    props: {
      jobs,
    },
  };
}

问题原因

  1. queryKey与初始数据的请求参数不匹配:getStaticProps中调用fetchJobs只传入了pageNumber和orderBy,但组件中useQuery的fetchJobs传入了5个参数(其余初始为空字符串)。这导致react-query认为当前queryKey对应的缓存不存在,会自动发起新请求,触发isLoading。
  2. react-query默认的重新验证机制:react-query默认staleTime为0,即数据一旦挂载就会被标记为"过时",会自动后台重新请求数据,导致isLoading短暂变为true。

解决方案

1. 对齐初始请求参数与queryKey

修改getStaticProps,确保调用fetchJobs时传入的参数与组件初始状态的参数完全一致,这样初始数据对应的queryKey才会和组件的初始queryKey匹配:

export async function getStaticProps() {
  const pageNumber = 1;
  const company = "";
  const remote = "";
  const orderBy = "date";
  const location = "";

  const jobs = await fetchJobs(pageNumber, company, remote, orderBy, location);
  return {
    props: {
      jobs,
    },
  };
}

2. 设置staleTime禁止自动重新验证

在useQuery配置中添加staleTime: Infinity,这样react-query会认为初始数据永远是新鲜的,不会自动发起重新请求,只有当queryKey变化(过滤器修改)时才会重新获取数据:

const { data: jobData, isLoading } = useQuery(
  ["jobs", pageNumber, company, remote, orderBy, location],
  () => fetchJobs(pageNumber, company, remote, orderBy, location),
  { 
    initialData: props.jobs,
    staleTime: Infinity // 禁止自动重新验证
  }
);

额外优化:控制isLoading的显示逻辑(可选)

如果仍担心边界情况,可以结合isInitialLoading来判断初始加载状态(react-query v3+支持该属性),只在首次无初始数据时显示加载状态:

const { data: jobData, isLoading, isInitialLoading } = useQuery(
  // ... 其他配置
);

// 仅在真正的首次加载(无初始数据)时显示加载
if (isInitialLoading) {
  return <Loading />;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 19:39:26