Closed vsaarinen closed 3 years ago
this looks surprisingly similar to https://github.com/tannerlinsley/react-query/issues/1653
Don't know how the tests are written but it might be good to check if they do not implicitly depend on certain timings. Are you able to reproduce it manually? This might be useful: https://docs.cypress.io/guides/core-concepts/retry-ability.html
Don't know how the tests are written but it might be good to check if they do not implicitly depend on certain timings. Are you able to reproduce it manually? This might be useful: https://docs.cypress.io/guides/core-concepts/retry-ability.html
I haven't noticed this problem when using the app manually, so there's always a chance that this is somehow caused by Cypress. But a few reasons why I think this may be an issue with react-query:
useQuery
call returns undefined
for data
.I'll see if I can narrow down the react-query version where this started happening.
I can confirm the same behavior after migrating from 2.23.1 to 3.5.16.
isLoading
is randomly returning true for queries with staleTime
option. Everything works without staleTime
.
Would be great if you guys could to provide a sandbox or something similar which we can use to debug the issue.
Would be great if you guys could to provide a sandbox or something similar which we can use to debug the issue.
I've tried to reproduce in a sandbox without any luck (
Commenting just to subscribe to the thread because I'm having the same issue and can't reproduce it on a sandbox. Happens on v2.26.3 and after updating to v3.6.0.
Can we try to narrow it down collectively? So far, we've seen that:
2.23.1
according to @antonversal 2.26.3
according to @josewhitetower could you further narrow it down to a specific version between those two?
staleTime
seems to be involved, but how do you set staleTime? via the default-config on the global cache like @vsaarinen has shown in the opening post (similar to what @fTrestour has posted in #1653), or are you setting the staleTime
on the useQuery
call directly?
I'm also seeing that both the opening post in this issue as well as in #1653 have the retry
option set - could we rule that one out as well?
@TkDodo I set staleTime
in useQuery
. No global settings and retry
.
Can we try to narrow it down collectively? So far, we've seen that:
- it apparently still works on
2.23.1
according to @antonversal- it's no longer working on
2.26.3
according to @josewhitetowercould you further narrow it down to a specific version between those two?
For me, things work fine on 2.26.4
. I'll try to find which version of 3 causes things to start breaking again.
Started seeing the same issues after upgrading to 3.2.0
from 2.26.4
. So it appears to be a regression introduced in version 3.
Started seeing the same issues after upgrading to
3.2.0
from2.26.4
. So it appears to be a regression introduced in version 3.
I have the same issue
I finally found the cause at least for my specific case.
React-query performs a deep compare to update the component, so if your request returns the same data than in the previous request, react query will not update your component. This was happening randomly to me because the response of my request contains random changes but sometimes returns the same data. In my case I expect a re-render always. The solution in case you have the same problem is to disable deep compare by setting structuralSharing to false like this:
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
structuralSharing: false
}
}
});
This is a bug or at least confusing because it's an "anti-pattern" since react does not expose anything that works with deep compare like this. React is based on reference equality only.
This feature was introduced recently: https://github.com/tannerlinsley/react-query/issues/430
@fermmm It sounds like your issue may be different than what I'm experiencing. My issue is that even though data was successfully received by the app, useQuery
thinks that it's still loading the data and never provides it to the app.
@fermmm It sounds like your issue may be different than what I'm experiencing. My issue is that even though data was successfully received by the app,
useQuery
thinks that it's still loading the data and never provides it to the app.
Yes my problem looks similar but may be not the same.
Ok I had this issue in another request of my app and this time was not related with structuralSharing, I noticed {data: undefined, isLoading: true} randomly without getting the data. The only different thing with this useQuery() it was that I had many components mounted using the same useQuery() key, maybe is something that happens when one component is waiting for the request and other mounts with the same... I don't know.
Same problem here. In my case I use staleTime: Infinity
.
I would really like to get to the bottom of this issue, but if nobody can reproduce it in a codesandbox, it is almost impossible to narrow down.
I forgot to add more info: I'm mounting a lot of components (50) that use this useQuery
with Infinity
staleTime
and I don't have configured retry
neither. I'm going to try to reproduce it in a sandbox.
I have created a sandbox with the conditions that seem to be common to all of us (Infinity staleTime and having many instances) but cannot reproduce the error, I think it has only happened to me once. On my SPA it happens to me much more easily 🤔
From what I can see in the sandbox: are you also putting the whole result from fetch
into the query cache in your app? This includes some non-serializable data, like the body
, which is a stream, and lots of functions that return Promises, like .json()
...
No no, it was like this because since I don't use data
in the example I didn't even worry with the response. I updated it and now I just return the JSON body (like in my app of course)
In my case this only happens when I restart my RN app when all the components are loading for the first time
I believe my issue has also appeared only on app start, in the initial loading of components.
I believe my issue has also appeared only on app start, in the initial loading of components.
I guess this is the only time when you can be "stuck in loading", because you are never in loading state again once you've successfully loaded data.
Question: In case this being-stuck happens, what do the react-query devtools say about the state of the query?
Question: In case this being-stuck happens, what do the react-query devtools say about the state of the query?
The problematic query is the second from the bottom in the list, with 5 listeners and marked as stale:
I confirmed that the data for that query was received successfully when looking at the network developer tab. The weird thing is that the data is shown correctly in the devtools, but in our app the data
property of the objected returned by that useQuery
is undefined. Is there something more specific I should share from the devtools?
The weird thing is that the data is shown correctly in the devtools, but in our app the data property of the objected returned by that useQuery is undefined.
Yes, that does indeed seem weird. Are you using different staleTimes
on the 5 observers? Everyone is mentioning staleTime: Infinity
, but in your code, I am seeing a different staleTime
- and your query is also marked as stale
, which shouldn't be the case with staleTime: Infinity
...
Yes, that does indeed seem weird. Are you using different
staleTimes
on the 5 observers? Everyone is mentioningstaleTime: Infinity
, but in your code, I am seeing a differentstaleTime
- and your query is also marked asstale
, which shouldn't be the case withstaleTime: Infinity
...
I've never used staleTime: Infinity
. Except for a couple of queries where these are overridden, I only use the time values from the defaultConfig
as shown in the original post:
staleTime: 10 * 60 * 1000,
cacheTime: 15 * 60 * 1000,
Could the issue be somehow related to the fact that the devtools marks the query as stale even though it shouldn't be? Just guessing here since I don't know what "stale" means...
I've never used staleTime: Infinity.
thanks, I mixed that up a bit 😅 .
since I don't know what "stale" means.
a stale
query is a query that will refetched in the background if a new subscriber mounts / the window is refocussed etc.
the devtools marks the query as stale
judging from the code, the devtools don't manipulate the queries (unless you press one of the buttons). They just display the current state of the cache.
So if your screenshot is from after the 5 subscribers mount, and you have a staleTime
of 10 minutes - why are the queries showing up as stale
? They should show up as fresh
(green) - just like the other queries 🤔
So if your screenshot is from after the 5 subscribers mount, and you have a
staleTime
of 10 minutes - why are the queries showing up asstale
? They should show up asfresh
(green) - just like the other queries 🤔
Good question. The top 6 queries in the list should be marked as fresh. Maybe this is related to the underlying cause?
Good question. The top 6 queries in the list should be marked as fresh. Maybe this is related to the underlying cause?
yes, maybe. Are you sure that all subscribers (all instances of useQuery
) use the same config? If you have 4 subscribers with staleTime: 10 minutes, and one additional subscriber where the staleTime is 0, the smaller one will "win". Not sure if that could cause this problem ...
Are you sure that all subscribers (all instances of
useQuery
) use the same config? If you have 4 subscribers with staleTime: 10 minutes, and one additional subscriber where the staleTime is 0, the smaller one will "win". Not sure if that could cause this problem ...
All of the subscribers listed in the screenshots use the default cacheTime
of 15 minutes and staleTime
of 10 minutes.
Seems like the cache is fine, but maybe one of the observers did not get updated somehow. Can you see in the devtools if one of the observers for that query has an incorrect currentResult
?
Seems like the cache is fine, but maybe one of the observers did not get updated somehow. Can you see in the devtools if one of the observers for that query has an incorrect
currentResult
?
Yep, there's an issue with the observers: the first three have the correct data in currentResult
but the last one has invalid data, as shown in the screenshots below.
Just guessing here, but it seems technically possible that a query gets updated between a component mount and its useEffect.
In such case the component would miss the update.
Could you check if this change fixes it?
--- a/src/core/queryObserver.ts
+++ b/src/core/queryObserver.ts
@@ -528,6 +528,11 @@ export class QueryObserver<
)
if (query === prevQuery) {
+ if (query.state !== this.currentResultState) {
+ const prevResult = this.currentResult
+ this.updateResult()
+ if (prevResult !== this.currentResult) {
+ this.notify({ listeners: true })
+ }
+ }
return
}
Could you check if this change fixes it?
After a few quick tests, it does seem like this fixes the issue. 🎉 But need to do a bit more testing...
I added the following console logging to make sure that the condition gets hit, and the weird thing is that the this.notify()
never seems to be get called but the issue still seems to be fixed. Might the this.updateResult()
call be enough to fix this?
if (query === prevQuery) {
if (query.state !== this.currentResultState) {
console.warn('!!! query.state !== this.currentResultState !!!')
const prevResult = this.currentResult
this.updateResult()
if (prevResult !== this.currentResult) {
console.warn('!!! prevResult !== this.currentResult !!!')
this.notify({ listeners: true })
}
}
return
}
Note that I had to upgrade my local react-query
's copy of the react
and react-dom
devDependencies in order to be able to yarn link
it to my project. This probably doesn't have an effect on this issue, however.
I can confirm the same behavior after migrating from 2.23.1 to 3.5.16.
isLoading
is randomly returning true for queries withstaleTime
option. Everything works withoutstaleTime
.
I'm currently experiencing this same issue. I started a discussion on this yesterday. Here
Could you check if the issue is fixed in v3.6.1?
Haven't run into failing tests after upgrading to 3.6.1. Let's keep our fingers crossed.
Thanks a lot for the fix!
It seems to solve the problem in my case. Thank you very much!!
Thanks, @boschni. I do not see failing tests anymore as well.
Hello everyone!!!
Has anyone experienced the same behavior but now with useQueries hook
?
it doesn't return data and gets stuck in loading randomly in the tests. I appreciate any support
"react": "^16.13.1"
"react-query": "^3.13.4"
@ivillarreal91 I'm seeing this as well with latest, were you able to find a solution? Using useQuery
in one component and useQueries
with the same key in another component causes the useQuery
to get stuck. Going to try to reproduce in a CSB.
@ivillarreal91 I'm seeing this as well with latest, were you able to find a solution? Using
useQuery
in one component anduseQueries
with the same key in another component causes theuseQuery
to get stuck. Going to try to reproduce in a CSB.
I think this is the closest thing that describes the problem, I am currently having a similar issue and I just upgraded to the latest release. if you have keys like baa
and baaFoo
, the whole pages hangs and is stuck on isFetching
@Toyurc if you have a codesandbox reproduction, please open a new issue with it.
I have the same issue, its stuck at loading, while the exact same code works on another app.
@MatkoMilic again, this is not very helpful I'm afraid. Without an isolated reproduction, there is only so much I can do 🤷
@TkDodo I am also facing the same issue and stuggling to reproduce it.
I also have the same issue in my react native application, it is a random issue, sometimes isLoading and isFetching get stuck and data stays undefined even if the network request is done successfully. When I restart the app it works fine! Hopefully they can fix this issue as soon as possible
Describe the bug After upgrading to react-query 3.5.11 from 2.26.4 last week, our project's Cypress tests started failing randomly because the app started showing a loading spinner at random times. After a lot of head-banging, we finally tracked down the issue: even though, based on the network inspector, the request had gone through successfully, react-query's
useQuery
was returning an object withisLoading
astrue
anddata
asundefined
. Reverting back to react-query 2 fixed the problems.Most of the requests in our Cypress tests are stubbed using
cy.server
andcy.route
. This probably shouldn't affect react-query but mentioning it here just in case.Our cache is configured in the following manner at the top of one of our source files, so this shouldn't be caused by us accidentally creating multiple caches:
To Reproduce Unfortunately, this happens randomly and is thus very hard to reproduce. The randomness does point towards some type of race condition. Our app performs many (~10) requests on startup.
Even though which tests fail is random, I can consistently get at least one test to fail. Is there something I can do to help track down what could be the issue?
Expected behavior
useQuery
should return the data it receives in the response once the request is successful.Desktop (please complete the following information):
Additional context Happens on both Cypress version 5.3.0 and 6.2.1.