Closed burnedikt closed 3 weeks ago
I had the same issue trying to update a variable inside useQuery
whitout updating the queryKey
useQuery will only update the variables within it if the queryKey
is changed. As it stands, even changing the retryDelay the query will not have its values ​​updated, since the queryKey
has not changed
If you change line 12 to this one you will see that the problem has been solved
queryKey: ['test', retryDelay],
refetchInterval
is used to revalidate the query, so it will only work if it is successful.
I think that it happens because of the caching in react-query. The function will not update is own values if the key doesn't change, it will only update the data.
Maybe I'm making a mistake trying to prove you my point (I've heard it while a go, so that is the reason that I know it), but maybe the useQuery
component will only trigger the useEffect
and rerender it state when some of the options in queryKey, queryFn changes.
https://github.com/TanStack/query/blob/main/packages/react-query/src/useBaseQuery.ts#L91
the options do update on the query, but not on the retry. Let me explain:
when a query starts to run, we create an internal retryer
and pass options from the query to it:
Then, that retryer takes those options, returns a promise and will resolve or reject it once the whole process of fetching is complete. This takes retries, network availability etc. into account. Fore example, the query might go into paused
state in between and continue with retries later.
So the retryer will see the options from the time it was created (=when the fetch started). Usually, this is what you want because the retry process is opaque. The promise will resolve or reject eventually, and then, when a refetch
occurs (which is different from a retry
), the new values will be respected.
We could make those values reactive in between retries, but I think that'll open up a can of worms. What if you change retries from 5
to 2
while you are at the 3rd retry? What if you change networkMode
to 'always'
while the query is paused
because you have no network connection? It's the safer approach to just trigger the whole process (fetch + retries) with a given set of options from creation time until it is finished. It's a bit how closures work with react functions, too.
Both retry
and retryDelay
can be a function, so you can define them as a function and use a ref
to read the latest value inside of it if you really want.
Describe the bug
tl;dr; When
retryDelay
is updated (e.g. based on a react state variable) theuseQuery
hook does not seem to update the underlying retryer.I've tried to build a query which polls an endpoint until it succeeds. Per default, it's okay to have quite a forgiving and long retry delay but based on some user action, I can actually assume the query might succeed sooner and I wanted to adjust the
retryDelay
(basically using it as polling interval in this case) accordingly. I then introduced a state variable which I update over the course of time and was expecting the query retry logic to adapt to it - but it didn't.Your minimal, reproducible example
https://stackblitz.com/edit/vitejs-vite-u6rzza?file=src%2FApp.tsx
Steps to reproduce
retryDelay
retryDelay
option ofuseQuery
retryDelay
don't take effectExpected behavior
As a user, I expected that changes to the query configuration (like changing the
retryDelay
) will have an effect and change the query's behaviour but instead (and contrary to other query options like e.g.refetchInterval
) a change in theretryDelay
did not change the retry behaviour of the query.How often does this bug happen?
Every time
Screenshots or Videos
No response
Platform
Tanstack Query adapter
react-query
TanStack Query version
v5.29.2
TypeScript version
v5.2.2
Additional context
I am aware there are workarounds out there like using
refetchInterval
instead (this is the same example from the reproducible stackblitz usingrefetchInterval
instead) but this requires considering the queryFn not failed so that the refetch can happen and then check based on the (fake)data
whether or not to keep refetching.Another workaround I found is to include the
retryDelay
within thequeryKey
but while this gets the job done, it feels very awkward.I don't consider this to be a big issue and probably an edge case but it still looks like unexpected behaviour to me and it cost me a couple of hours figuring out what's going on, so I thought I'd share it.