我已经在next.js应用程序上使用react query实现了数据获取和更新的基本功能。我的目标是更新突变后的数据。目前,数据仅在选项卡刷新时更新。但如果没有用户交互,它不会改变
我发现选项卡刷新时的数据更新是因为refetchOnWindowFocus
的默认行为
但是如何在服务器端更新数据后使其无效。以下是相关的代码片段
注意:我正在使用反应查询SSR功能,使用水合。文档
_app.jsx
const [queryClient] = React.useState(() => new QueryClient());
return (
<QueryClientProvider client={queryClient}>
<Hydrate state={pageProps.dehydratedState}>
<Component {...pageProps} />
</Hydrate>
</QueryClientProvider>
主页.jsx
const {data} = useQuery({
queryKey: [queryKeys.key],
queryFn: fetchData,
staleTime: 1000 * 10, // this doesn't affect on anything
//refetchInterval: 2000, this updates every 2 seconds
});
return (
<div>
<Article articles={data} />
</div>
);
export const getServerSideProps = async () => {
const queryClient = new QueryClient();
await queryClient.prefetchQuery([queryKeys.key], fetchData);
return { props: { dehydratedState: dehydrate(queryClient) } };
};
Article.jsx
const Article = ({articles}) => {
const [title, setTitle] = useState("");
const queryClient = new QueryClient();
const { mutate } = useMutation({
mutationFn: async (article) => {
return await axios.post(url, article);
},
onSuccess: (data) => {
console.log("data", data) // data is displayed, onSuccess is called
queryClient.invalidateQueries({ queryKey: [queryKeys.key] });
},
});
const changeTitleHandleClick = () => {
mutate({
id: new Date(),
title: title
});
setTitle("");
};
....
如有任何帮助,将不胜感激
更新:refetchInterval: 2000
每2秒更新一次,但这会每2秒触发一次网络请求,所以我不确定这是否是重新确认的最佳做法
UPDATE:onSuccess
方法内部的控制台在突变时显示,这意味着逻辑有问题,因为即使键不同,这也应该起作用:queryClient.invalidateQueries()
,我没有指定任何键,而是触发所有查询。但即使这样也不会更新。为什么?
实现突变的方式,应该在成功突变后重新生成查询:
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [queryKeys.key] });
},
如果这不起作用,要么你的突变没有成功。检查是否调用了onSuccess
回调。
如果调用了onSuccess
回调,但您的查询没有被重新蚀刻,则可能意味着queryKey
不匹配。出于测试目的,尝试将过滤器扩展为:
queryClient.invalidateQueries()
它应该重新引用所有查询。如果这样做有效,那么您就知道queryKey
过滤器不匹配。
更仔细地看,你正在失效:
queryKey: [queryKeys.key]
但在您的自定义挂钩中,您使用的是:
queryKey: [queryKeys.articles]
因此,它们看起来确实不同,因此不匹配。此外,一定要使用@tanstack/react-query-devtools
来更好地了解缓存中的查询和密钥。
问题是在组件Article.jsx
中,我在每个渲染中都创建了一个新的QueryClient,因此它获得了一个新快取,因此没有更新
相反,我不得不使用useQueryClient
钩子,它返回当前实例const queryClient = useQueryClient();