I am creating a dating app's swiping page in React using TanStack Query. When swiping on the last user in a batch of profiles received from the database, the user has to wait for the next batch to be fetched, which causes a delay, so I was looking for a solution in TanStack Query to solve the issue. I've read through the docs and consulted AI on how to use their prefetch functionality, but the docs seem unclear to me, and the AI generates straight-up wrong solutions. I am aware that I could separate the batch of profiles to be shown from the batch of profiles bound to useQuery and update the former whenever the latter changes, but I feel like that would defeat the purpose of using TanStack Query in the first place and would mess up the caching, as states are lost when the component unmounts, so if the user shortly left the swiping page and came back, they'd be faced with a different person than they were seeing when they left.
I have tried this, and I expected the prefetchQuery to remove the need for loading after swiping on the last profile in a batch from the database because I thought the new batch would be saved in cache. In reality, what happens is that after every swipe, a new batch is requested and the app loads, as if the prefetchQuery was simply a normal Query. I set the staleTime to 0 with the idea that the prefetch should always ignore the current cache to get a new batch of profiles, but if I set the staleTime to Infinity, the prefetchQuery simply behaves as if it weren't there at all.
import api from "../api";
import ProfileCard from "./ProfileCard";
import { useQuery, useQueryClient } from '@tanstack/react-query'
import Loading from "./Loading";
import Error from "./Error";
const Home = () => {
const queryClient = useQueryClient();
const fetchProfiles = async () => (await api.get('swipe/')).data
const { data: profiles, isError, isFetching } = useQuery({
queryKey: ['swipe'],
queryFn: fetchProfiles,
staleTime: Infinity,
});
if (isFetching) {
return <Loading />;
} else if (isError) {
return <Error />;
}
const swipe = () => {
if (profiles.length === 9) queryClient.prefetchQuery({ // Profiles are fetched in batches of 9, so this should happen on the first swipe of a batch
queryKey: ['swipe'],
queryFn: fetchProfiles,
staleTime: 0,
});
if (profiles.length === 1) queryClient.refetchQueries({ queryKey: ['swipe'] });
else queryClient.setQueryData(["swipe"], profiles => profiles.slice(1));
}
return (
<>
<ProfileCard profile={profiles[0]} />
<button onClick={swipe}>Left</button>
<button onClick={swipe}>Right</button>
</>
);
}
export default Home;