我测试react-query和SSR从nextjs预取数据只有当staleTime过去了。但是在测试之后,每20秒都会向API发出一个新的get请求,即使staleTime超过20秒。我真的不明白为什么这就是代码:
索引:
import { dehydrate, QueryClient, useQuery } from "@tanstack/react-query";
import Image from "next/image";
import axios from "axios";
type SpaceXData = {
name: string;
links: {
patch: {
large: string;
};
};
};
const getSpaceXData = async () =>
await (
await axios("https://api.spacexdata.com/v4/launches/latest")
).data;
export default function Page() {
const { data } = useQuery<SpaceXData>(["spacex"], getSpaceXData);
console.log(data);
if (!data) return <h1>Error</h1>;
return (
<div>
<h1>{data.name}</h1>
<Image
src={data.links.patch.large}
alt="image"
width={500}
height={500}
/>
</div>
);
}
export async function getStaticProps() {
const queryClient = new QueryClient();
await queryClient.prefetchQuery(["spacex"], getSpaceXData, {
staleTime: 30000,
});
return {
props: {
dehydratedState: dehydrate(queryClient),
},
};
}
_app.tsx:
import "tailwindcss/tailwind.css";
import type { AppProps } from "next/app";
import {
QueryClient,
QueryClientProvider,
Hydrate,
} from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import React from "react";
function App({ Component, pageProps }: AppProps) {
const queryClient = React.useRef(
new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
retry: false, staleTime: 30000,
},
},
})
);
return (
<QueryClientProvider client={queryClient.current}>
<Hydrate state={pageProps.dehydratedState}>
<Component {...pageProps} />
</Hydrate>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
export default App;
使用react-query devtools,我可以看到数据只有在30秒后才会过期,但在这30秒之间,一个请求完成,其他都是缓存请求。我尝试在axios请求上设置超时,但行为是相同的。也许是因为我有两个查询客户端,或者可能是下一个SSR正在进行重新验证。
1条答案
按热度按时间pvabu6sv1#
如果我误解了这个问题,请告诉我,但是当你在页面之间导航时,听起来你看到的是服务器上的抓取?注意,在开发模式下,每个请求都会调用
getStaticProps
。对于服务器端渲染,我们必须区分两种场景:
1.在服务器上发生获取。这是你的
getStaticProps
。1.在客户端上发生获取。这可能是由react-query触发的重新获取,或者因为新的useQuery示例挂载等。
QueryCache位于QueryClient内部,这就是为什么要在
_app.tsx
的示例引用中创建一个QueryCache的原因。此QueryClient将在客户端/浏览器上可用-仅适用于场景2)这也是QueryClient,当页面第一次呈现时,它从服务器获取数据水合。
但是在服务器上,在
getStaticProps
内部,每次都新创建queryClient:这意味着当您进行预取时,客户端内部该高速缓存是空的(因此将
staleTime
放在那里并没有实现太多)。因此,您还需要对这些请求进行重复数据删除,这是某种服务器端缓存。如果您将queryClient放在
getStaticProps
之外,它将位于服务器的内存中,但数据将在所有用户之间共享,这就是为什么不鼓励这样做的原因。服务器端缓存是一种完全不同的缓存,你可以考虑将QueryClient的结果存储在redis中并重用它,但这通常不值得。特别是因为getStaticProps
只在开发模式下对每个请求调用,而不是在生产模式下。这更像是一个getServerSideProps
问题。