T
TanStack•15mo ago
stormy-gold

Long waiting time for queryFn to run

Hi, I'm experiencing a strange issue with react-query. When the useQuery function is mounted, and I can see it registered in the devtools, it takes several milliseconds (1500 - 3400) to run queryFn. My code:
const { data, refetch } = useQuery<Stop>({
queryKey: ["stop", city, stop],
queryFn: () => fetchStop(city, stop, limit),
});
const { data, refetch } = useQuery<Stop>({
queryKey: ["stop", city, stop],
queryFn: () => fetchStop(city, stop, limit),
});
and queryClient options:
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnMount: true,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
},
});
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnMount: true,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
},
});
38 Replies
extended-salmon
extended-salmon•15mo ago
I don't understand the video. Where is the 3 second delay? I guess you have already tried to make a log statement inside the queryFn before you call fetchStop to see when it gets executed ?
stormy-gold
stormy-goldOP•15mo ago
look at chrome devtools and query devtools, you can see that request pop ups several miliseconds later and i did that with console
extended-salmon
extended-salmon•15mo ago
and the log is also delayed ?
stormy-gold
stormy-goldOP•15mo ago
yes and fetchStop is simple fetch but with auth headers
stormy-gold
stormy-goldOP•15mo ago
No description
stormy-gold
stormy-goldOP•15mo ago
it's exactly 1 second which is a bit too long
extended-salmon
extended-salmon•15mo ago
so you've done this?
console.log('render', Date.now())
const { data, refetch } = useQuery<Stop>({
queryKey: ["stop", city, stop],
queryFn: () => {
console.log('queryFn', Date.now())
return fetchStop(city, stop, limit),
}
});
console.log('render', Date.now())
const { data, refetch } = useQuery<Stop>({
queryKey: ["stop", city, stop],
queryFn: () => {
console.log('queryFn', Date.now())
return fetchStop(city, stop, limit),
}
});
and there is 1 second between those ?
stormy-gold
stormy-goldOP•15mo ago
almost exactly
No description
extended-salmon
extended-salmon•15mo ago
hm, could be rendering related, as the fetch is triggered after render. Can you make a minimal return after the useQuery, like an empty div or so to check ? but then it wouldn't show up as fetching in the devtools either. There isn't any code between those lines though. We set the query to fetching state (which is what the devtools show), and then we create a retryer and start fetching, which calls the queryFn.
stormy-gold
stormy-goldOP•15mo ago
like this?
stormy-gold
stormy-goldOP•15mo ago
No description
extended-salmon
extended-salmon•15mo ago
yeah
stormy-gold
stormy-goldOP•15mo ago
still the same
No description
extended-salmon
extended-salmon•15mo ago
this should be impossible 😂 okay query devtools show multiple observers. Are there other components using the same query? We need to trim it down to a minimum until those logs match up
stormy-gold
stormy-goldOP•15mo ago
i can change querykey on main component oh that was it
stormy-gold
stormy-goldOP•15mo ago
No description
stormy-gold
stormy-goldOP•15mo ago
but it's weird
stormy-gold
stormy-goldOP•15mo ago
that's the other observers
No description
No description
extended-salmon
extended-salmon•15mo ago
multiple observers is fine, but only one of them is triggering the fetch. Maybe there is something blocking going on in one of the other components? again, try trimming it down by returning empty divs / remove other hook calls etc
extended-salmon
extended-salmon•15mo ago
in isolation, theres like 5ms difference between render and fetch
No description
stormy-gold
stormy-goldOP•15mo ago
still the same
No description
No description
No description
No description
extended-salmon
extended-salmon•15mo ago
so which of the 3 do you have to comment out to get better numbers?
stormy-gold
stormy-goldOP•15mo ago
those with no queryFn i can try giving them queryFn
extended-salmon
extended-salmon•15mo ago
aah I didn't see that. no queryFn is bad I see what's happening the one without queryFn probably renders first, that initiates the fetch. It doesn't have a queryFn, so it errors out with "no queryFn found". Then retryDelay kicks in, and 1second later, it starts to work That's also why you see it in fetching state in the devtools
stormy-gold
stormy-goldOP•15mo ago
ohhhh that makes sense
extended-salmon
extended-salmon•15mo ago
why would you make a query without a queryFn 😂
stormy-gold
stormy-goldOP•15mo ago
well it works on production
extended-salmon
extended-salmon•15mo ago
coincidentally maybe
stormy-gold
stormy-goldOP•15mo ago
until I fully stopped using redux
extended-salmon
extended-salmon•15mo ago
okay just don't do it please. extract the key + fn to a query factory, use queryOptions and use those options in all places: https://tkdodo.eu/blog/the-query-options-api
The Query Options API
v5 brought a new, powerful API, especially if you're using React Query with TypeScript...
stormy-gold
stormy-goldOP•15mo ago
okay, i have used this:
No description
stormy-gold
stormy-goldOP•15mo ago
thank you for help
extended-salmon
extended-salmon•15mo ago
eh, but why? this isn't reactive, so the component won't re-render on its own if new data comes in what's wrong with calling useQuery with the same key and the same function as in other places? if you're worried about too many refetches, just set staleTime
stormy-gold
stormy-goldOP•15mo ago
the main component has limit param that is not accessible from any other file so there is no other option that useQuery to get latest data
extended-salmon
extended-salmon•15mo ago
yeah I've seen the limit param. If it's used in the queryFn, it also needs to go into the queryKey otherwise, changes in limit won't trigger refetches so in general, all dependencies for a query need to be in the key (we have a lint rule for that), and they need to be available wherever you want to use the query
stormy-gold
stormy-goldOP•15mo ago
Can I keep the queryKey as it is, add queryFn to the child components with a default value for limit, and then have the main component manage the actual limit and perform refetch()?
extended-salmon
extended-salmon•15mo ago
I can't rule out stale closure problems with that approach. If the limit can change, why not add it to the key? You'll also overwrite cache entries with different limits this way ...
stormy-gold
stormy-goldOP•15mo ago
that's the point, if limit goes up I don't need to access old requests with lower limits

Did you find this page helpful?