I implemented the basic implementation of data retrieval and update using react-query on my next.js application. My goal is to update the data after mutation. Currently, the data is only updated when the tab is refreshed. But it won't change without user interaction.
I found that the data update happening on tab refresh is due to refetchOnWindowFocus
default behavior.
But how does it become invalid after the data is updated on the server side? Here is the relevant code snippet.
Note: I am using Hydration to use the react-query SSR functionality. document
_app.jsx
const [queryClient] = React.useState(() => new QueryClient()); return ( <QueryClientProvider client={queryClient}> <Hydrate state={pageProps.dehydratedState}> <Component {...pageProps} /> </Hydrate> </QueryClientProvider>
Home.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(""); }; ....
Any help would be greatly appreciated
Update: refetchInterval:2000
Updates every 2 seconds, but this triggers a network request every 2 seconds, so I'm not sure this is a best practice for revalidation.
UPDATE: onSuccess
The console inside the method is showing on mutation, which means there is something wrong with the logic since this should work even if the keys are different: queryClient .invalidateQueries()
where I did not specify any key but triggered all queries.
But even then it won't be updated. Why?
P粉6776848762024-03-26 11:50:35
The way you implement mutation, it should re-fetch the query after successful mutation:
onSuccess: () => { queryClient.invalidateQueries({ queryKey: [queryKeys.key] }); },
If this doesn't work, your mutation was unsuccessful. Check if the onSuccess
callback is called.
If the onSuccess
callback is called, but your query is not re-fetched, it may mean that the queryKey
does not match. For testing purposes, try expanding the filter to:
queryClient.invalidateQueries()
Should re-fetch all queries. If it works, you know your queryKey
filter doesn't match.
Look carefully, you are failing:
queryKey: [queryKeys.key]
But in your custom hook you are using:
queryKey: [queryKeys.articles]
So it looks like they are indeed different and therefore not matching. Also, be sure to use @tanstack/react-query-devtools
to better understand the queries and keys in the cache.
P粉2310799762024-03-26 11:47:03
The problem is that in the component Article.jsx
I create a new QueryClient on every render, so it gets a new cache and therefore is not updated.
Instead, I have to use the useQueryClient
hook, which returns the current instance.
const queryClient = useQueryClient();