-
Notifications
You must be signed in to change notification settings - Fork 787
When variables change, data is the previous result in Query Component #2202
Comments
Yeah, you basically have to use something like this to prevent rendering data from a query with different variables: if (data.reddit && data.reddit.subreddit.name !== this.state.search) {
data = {};
} And that only works if the data being returned also includes the variable you passed in. Definitely seems like a bug. |
This is a pretty common issue. You need to do a check for equality of a
name/id and show a loading component or pass an empty/default obj if you
don’t want to see stale data. I would advise modifying the data variable,
if that’s the same one from the query result obj. Just use a ternary or
if/else. You may need to abstract it to an external component to ensure you
get rerenders reliably.
…On Wed, Jul 25, 2018 at 10:45 AM James Wyatt Cready-Pyle < ***@***.***> wrote:
Yeah, you basically have to use something like this to prevent rendering
data from a query with different variables:
if (data.reddit && data.reddit.subreddit.name !== this.state.search) { data = {};
}
And that only works if the data being returned also includes the variable
you passed in. Definitely seems like a bug.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#2202 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AIM6lxQm220hAw84gsU2XQj043KYvC17ks5uKKCzgaJpZM4VZucg>
.
|
@sbrichardson the problem is that OP wants to see cached data for query when the variable is the same, but the problem is that Apollo is displaying the cached results for wrong query if the cached results for the current query do not already exist in the cache. The expected behavior is for Apollo to provide an empty The actual behavior is that Apollo is providing the previous Please see a more detailed example here. |
I do think that it can be valuable to show the previous result while the new one is loading. I have a search auto complete feature that does this. But I also need this case. I can't check for equality of a name or id because the query is a search query. The variables that are passed into the function child are the same as the current input so I can't check equality using that. |
@jcready - thanks for the clear description. I suppose that both behaviors could be desirable in different situations, and it’s a matter of which is default. With the suggested strategy it would be pretty pretty trivial to restore the current behavior by creating a component stores the Query’s variables/results in state and only updates them once the variables have changed and data is present. Changing the existing behavior in userland is a bit trickier, given that we don’t know which variables the current data is from. I agree that this is a bug. |
This issue also looks to be duplicated in #1342 and #1963 I believe the source of this issue is around this bit of logic in the Lines 391 to 400 in 2788981
Specifically line 392. Since a query with different variables will not have cached data, but will have previous data from the previous query with different variables, the To support pagination perhaps it is necessary to have the component accept some new prop which would either accept an array of variable keys which would invalidate the <Query
query={query}
variables={variables}
fetchPolicy="cache-and-network"
shouldInvalidatePreviousData={(nextVariables, previousVariables) =>
nextVariables.subreddit !== previousVariables.subreddit
}/> |
I agree that |
I've just stumbled across this bug. No news if this is going to be fixed? |
This is very weird. I'm almost sure I've seen this working well before in another app, but I'm facing this now too. It is most likely a matter of how the query is being cached. The cache's PK needs to be the query plus variables. |
first discovery here: if you use refetch instead of changing the props from the parent, the networkStatus (https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-networkStatus) will be 2 that's more appropriate than 1. If you pass from the parent it will be one. |
I agree with @jcready. That's probably the error due to the behavior I've observed here. I spent a lot of hours yesterday trying to find a workaround and this is the best I could come up with. I prefer using the graphql hocs approach together with recompose functions. Please adjust the solution to your scenario. The best way I could find to show correct data was to check if the query really has a cache and then to infer that the data is from the cache instead of from the previous variable set. I created this method to check for the cache:
And then this logic:
So, after that,
If someone has any simpler solution, please let us know here on this issue. |
I suspect I have the same problem, but with |
Encountered the same issue. Solution:
Relevent code: Lines 396 to 402 in 386b6d7
|
Is there any work around for this or plans to fix it? |
any update on this issue, this is a pretty big problem imo |
I also encountered this problem using HOCs. It only starts to work properly when fetchPolicy is set to 'no-cache'. Any update on this? |
Just bumped into this problem. It seems as if Apollo looks for a similar object in the cache and uses that without checking any variables. When cache persistence is enabled, even refreshing doesn't affect it, and the only way around it is to disable cache for the query, which is unacceptable when offline functionality is desired. I'd assume the client making a new query when variables changed and data for them isn't in the cache is a sane default. |
Encountering this, myself. I'll just have to turn off the cache for now, which is a bummer of a workaround. |
Also encountering this issue. |
I appreciate all the work done by the Apollo team but for me this is a very significant issue. |
I faced same issue and I put
|
@TuHuynhVan that's a workaround which won't work for everyone. In my case, being able to cache queries is critical as I'm working on a PWA with offline functionality. |
|
@jcready It won't solve this entire issue thread, I agree. But I have a feeling it will help address some of the comments posted here in the past 2 weeks. |
@hwillson, To me we already have three solid approaches on how to solve this problem:
The first approach is my favorite because is more of a declarative/reacty way of doing things. I guess the first two approaches would attend most of the use cases, but it does not invalidate the use cases solved by the third and I think after implementing one approach the other two would be trivial (guessing out of complete ignorance sorry if it is harder than it seems). The hooks version could have an array containing values that would cause the hook to clearPreviousData, it would work like the hooks version of the third approach. Just brainstorming here to let you all know that this problem is still a thing and to get the discussion running again. |
@hwillson, I am experiencing this problem when using
Setting |
@hwillson, my problem was actually the result of me not understanding how The {
"search": [
{
"id": 321,
"mpn": "NE555",
"median_price_1000": {
"currency": "INR",
"price": 0.123,
"__type": "PricePoint"
},
"__type": "Part"
},
{
"id": 654,
"mpn": "NE555P",
"median_price_1000": {
"currency": "INR",
"price": 0.456,
"__type": "PricePoint"
},
"__type": "Part"
},
{
"id": 987,
"mpn": "NE555R",
"median_price_1000": {
"currency": "INR",
"price": 0.789,
"__type": "PricePoint"
},
"__type": "Part"
}
]
} This over-simplified example was hiding the real cause of the problem. For anyone else who may be experiencing similar issues, by passing a import withApollo from 'next-with-apollo'
import ApolloClient, { InMemoryCache, defaultDataIdFromObject } from 'apollo-boost'
export default withApollo(
({ initialState }) =>
new ApolloClient({
cache: new InMemoryCache({
dataIdFromObject: (o: any) => {
const id = defaultDataIdFromObject(o)
if (o.__typename !== 'Part' || id === null) {
return id
}
if (o.median_price_1000 === null) {
return id
}
return `${id}:${o.median_price_1000.currency}`
}
}).restore(initialState || {}),
...
})
) This solved the caching problem without using |
@markplindsay The problem is that Apollo should warn you in development mode when your |
@hwillson can confirm this happens with "@apollo/react-hooks@^3.1.3" useQuery returns old data when variables change (with loading: true) Edit: but maybe that is intentional and could make sense in some cases |
@hwillson |
Same problem here, the data is always "one version" too old. |
Same here. |
Has anyone found a suitable workaround for this? |
@afreix the trick of adding a |
@declanelcocks could you elaborate? I'm having the same issue as others. I have a context in my React app that, when it changes, the When my context changes to a new variable, a query if executed and new data is populated. If I change my context back to a previously fetched variable, the If I change my fetchPolicy to |
Yeah also experiencing this issue in 3.1.0 and 3.1.1. |
I am facing the same issue with The order of Execution is as follows: FetchMore -> UpdateQuery({fetchMoreResult , variables}) -> then OnCompleted is Called. variables and fetchMoreResult in UpdateQuery are up to date; but the FYI it doesnt matter if my fetch policy is |
This still occurs on v2.6.8 for me which is a stable build. I think I have spent an honest 4 hours trying to fix this bug where
|
@mhuconcern I am facing the exact same issue with the version you mentioned |
@trdaya #321 (comment) . If this helps you. I realize that this bug even though it exists on this build, it is exposed more if your graphql apis don't have a way to define if the returned object is unique to the request param |
@mhuconcern thanks 👍 . I tried this but unfortunately, it didn't work for me.
I tried throttling my network on chrome's dev-tools and found that this issue doesn't happen on slow networks. |
Just incase anyone else is having issues working around this, comparing current
|
Worked for me. Thanks |
In my case I am doing the following
So when the |
@krvajal As far as I can see, the problem there is that if you do have the data in the cache you end up wiping it out then with that approach. The only approach I've currently seen working is somehow echoing some of the data included in your query variables in the data so you can see if the data is new or not. This is a huge issue for applications that want to show up-to-date data, but still respond extremely quickly and opportunistically, and I've not seen a good solution that doesn't rely on using the response data (which isn't always possible). |
This is proving to be such a big pain. Trying to fit in rxjs into the mix is fun(not). After spending a lot of time working with Angular, it's amusing to me that |
I am considering leaving development job and starting to work as a bus driver because of this bug. |
This comment has been minimized.
This comment has been minimized.
I was able to solve this by using a combination of client.resetStore() on my logout function and fetchPolicy='network-only' on my Query. |
I use new QueryData({
options: updatedOptions,
context: context,
onNewData: function () {
if (!queryData.ssrInitiated()) {
// update next tick
Promise.resolve().then(forceUpdate);
}
else {
forceUpdate();
}
},
});`` |
I am using the "cache-and-network" policy.
Intended outcome:
Rerender Query with different variables. Data is {} until new request is resolved from cache or network.
Actual outcome:
Rerender Query with different variables. Returns previous data until next query is resolved without error.
How to reproduce the issue:
https://stackblitz.com/edit/react-snlwzf
change the input and hit submit.
Version
Backgroud
I only want to display a loading state if I don't have a response from the cache or network, but I do want to show loading state when variables change and I don't have a response from cache. Right now it is impossible to tell if data is the response from cache or if it is the previous result. Loading property is no help because it is allows true until the network request is resolved.
The text was updated successfully, but these errors were encountered: