-
-
Notifications
You must be signed in to change notification settings - Fork 522
Query result called twice #492
-
Minimal example:
export default Vue.extend({
...
apollo: {
me: {
query: ME_QUERY,
result(res) {
console.log({ res });
},
},
},
created() {
console.log('created');
}
mounted() {
console.log('mounted');
}
...
});
Outcome:
screenshot 2019年01月19日 at 13 11 20
Query loads twice, before and after lifecycle hooks. Is this expected behaviour? Notice that the first result contains partial: false, and the second contains stale: false.
Expected outcome:
I only want result to be called once.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 10
Replies: 25 comments 2 replies
-
@nomadoda it looks like it might be related to caching https://imgur.com/a/1HUdfZa
Maybe someone that has read the Apollo API can bring some light to the tunnel!
Beta Was this translation helpful? Give feedback.
All reactions
-
@nomadoda I believe that the first response is the result you get from the cache.
Beta Was this translation helpful? Give feedback.
All reactions
-
Getting similar behaviour, looks to be cache related.
I don't understand the difference between the results either: partial, stale
If you set the fetchPolicy = "no-cache" then you no longer get the partial result "partial: false".
apollo: { me: { query: ME_QUERY, fetchPolicy: 'no-cache', // cache for this query only result(res) { console.log({ res }); }, }, },
You can turn this off globally using:
new ApolloClient({ cache, link, defaultOptions: { fetchPolicy: 'no-cache' } })
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 4
-
Ok, that makes sense. Is there any hook called once, when the query is finished?
Beta Was this translation helpful? Give feedback.
All reactions
-
I have the same issue. It's definitely cache related. The Apollo Component only calls result once so this behavior is confusing.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 4
-
Beware of using fetchPolicy: 'no-cache' because your query (which is a watchQuery) will no longer be reactive to cache changes. This means updating the queried object elsewhere in your app will not be reflected in the query using 'no-cache', and you will need to manually refetch. This largely defeats the purpose of using a watchQuery.
To get a single query result try using a fetchPolicy with 'cache-only' or 'network-only'.
For more info: https://www.apollographql.com/docs/react/api/apollo-client/#apolloclient-functions
Beta Was this translation helpful? Give feedback.
All reactions
-
Did someone find a solution?
Beta Was this translation helpful? Give feedback.
All reactions
-
fectchPolice: 'no-cache' works but loading will be always false, network-only doesn't work.
Beta Was this translation helpful? Give feedback.
All reactions
-
Since the query sent by ApolloQuery may be periodically re-issued (look at pollInterval), it's conceptually necessary that you be prepared to process a progressive sequence of revisions/updates to the result object. The idea with the two callbacks you are seeing in your log is that you got an initial set of answers from the cache followed by a refined set of answers from the network-based query to the server. Subsequent re-fetch operations may produce further refinements. Basic use (as documented and intended) of ApolloQuery exploits the fact that the result object is reactive to get your application UI to update dynamically, but more sophisticated patterns may need your application to "wrap" that object in a fashion that deals with the ongoing updates. Re-run your test with a pollInterval parameter of 1000 and watch what happens.
Now that I'm thinking about it, my guess is that the res object itself is identically the same object getting passed up the event tree over and over again. What I suspect is changing here is the content of the res object, and the fired event serves to signal that a change has occurred. Reusing the res object seems necessary for the normal reactive behavior to work. You could check this by saving the res object reference whenever you receive the event and printing an === comparison between the last one and one you are receiving in the event handler.
If you get multiple events as I expect, then this isn't a bug. In fact, it's an essential and necessary behavior.
Beta Was this translation helpful? Give feedback.
All reactions
-
I am also experiencing this with queries (ie. result or error is called twice back to back).
const apolloClient = new ApolloClient({ link, cache, connectToDevTools: !config.app.isProduction, defaultOptions: { query: { fetchPolicy: "cache-first", }, }, });
apollo: { viewer() { return { query: ViewerQuery, fetchPolicy: "network-only", result(result) { console.log(result); }, error(error) { console.log(error); } } } }
This results in the result or error being logged twice
Beta Was this translation helpful? Give feedback.
All reactions
-
Hi everyone, there any update about this issue?
Thanks in advance
Beta Was this translation helpful? Give feedback.
All reactions
-
no update here?
I count the same issue
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1
-
The same...Any results?
Beta Was this translation helpful? Give feedback.
All reactions
-
@nomadoda , did you solve this issue?
@Akryum, maybe you can suggest what could be a reason? Because I figured out that for vue-apollo 2.1.0-beta.9 it's work as expected
Beta Was this translation helpful? Give feedback.
All reactions
-
Beta Was this translation helpful? Give feedback.
All reactions
-
So it turns out this is not a bug. It's an intentional behavior. I gave an less-than-correct explanation above, but here's what's happening:
The first callback happens using the cached data on the client. The intent is to give the UI whatever data is already known so that it can get started.
The second callback happens when the network query returns values, which may be different from what was already in the client-side cache. For most objects returned from the network there will be no change, but a few will have changed, some may be added, and others may be dropped. Which means that a new response is required for the client view to revise what it shows.
You can confirm this by overriding the query behavior. If you set the query to "cache only" or "network only", you should find that the callback only occurs once.
This bug should be closed as not-a-bug. The behavior is correct and intentional.
Beta Was this translation helpful? Give feedback.
All reactions
-
This is still ocurring for me even with network-only (see comment above for config).
Beta Was this translation helpful? Give feedback.
All reactions
-
Beta Was this translation helpful? Give feedback.
All reactions
-
So it turns out this is not a bug. It's an intentional behavior. I gave an less-than-correct explanation above, but here's what's happening:
The first callback happens using the cached data on the client. The intent is to give the UI whatever data is already known so that it can get started.
The second callback happens when the network query returns values, which may be different from what was already in the client-side cache. For most objects returned from the network there will be no change, but a few will have changed, some may be added, and others may be dropped. Which means that a new response is required for the client view to revise what it shows.
You can confirm this by overriding the query behavior. If you set the query to "cache only" or "network only", you should find that the callback only occurs once.
This bug should be closed as not-a-bug. The behavior is correct and intentional.
@b-jsshapiro, Let's imagine that it is correct, like you said.
But why in vue-apollo 2.1 it works without two responses? And it works correct. Was it mistake?
Beta Was this translation helpful? Give feedback.
All reactions
-
@MaevskiyE: That's a good question, and the answer is: I don't know.
Perhaps if you put a breakpoint in the callback using the browser debugger, you'll be able to see in the callstack where the calls are happening from.
I'd do it here, but right now I'm focused on a server-side problem that's a bit urgent.
Beta Was this translation helpful? Give feedback.
All reactions
-
@NataliaTepluhina , very nice! Thanx a lot!
Beta Was this translation helpful? Give feedback.
All reactions
-
Consider you have the following:
<ApolloQuery :query="$MY.QUERY('document')" @result="setList" @loading="setLoading" @error="setError" > <my-list-component /> </ApolloQuery>
Then the is rendered twice. This is not the vue. It should be that what exists inside the ApolloQuery object should render once when is done.
Or am I missing something?
Beta Was this translation helpful? Give feedback.
All reactions
-
An apollo query result can be emitted with { loading: true, ... }
Beta Was this translation helpful? Give feedback.
All reactions
-
@b-jsshapiro suggested looking at the callstack. I did that (which is how I ended up here in the first place). I added console.log(new Error().stack) to the result hook like so:
result(data) {
console.log(new Error().stack)
this.customFunction();
},
Results:
Error
at VueComponent.result (ProfilePage.vue?8a4e:42)
at SmartQuery.nextResult (vue-apollo.esm.js?522d:996)
at SmartQuery.executeApollo (vue-apollo.esm.js?522d:898)
at SmartQuery.start (vue-apollo.esm.js?522d:643)
at SmartQuery.autostart (vue-apollo.esm.js?522d:530)
at DollarApollo.addSmartQuery (vue-apollo.esm.js?522d:1423)
at VueComponent.launch (vue-apollo.esm.js?522d:2020)
at invokeWithErrorHandling (vue.esm.js?a026:1863)
at callHook (vue.esm.js?a026:4228)
at VueComponent.Vue._init (vue.esm.js?a026:5017)
Error
at VueComponent.result (ProfilePage.vue?8a4e:42)
at SmartQuery.nextResult (vue-apollo.esm.js?522d:996)
at notifySubscription (Observable.js?a7b2:135)
at flushSubscription (Observable.js?a7b2:121)
at eval (Observable.js?a7b2:174)
at eval (Observable.js?a7b2:73)
It looks like the second has to do with subscriptions, but I'm not currently using any. My customFunction operates on the data, and this results in an array with all of the items duplicated. I guess I'll have to handle the double executions within my function.
Beta Was this translation helpful? Give feedback.
All reactions
-
I think the discussion if it is intended or not is useless, we need a event to be called only once to be aware that our query was executed and our data is avaliable, if the result is calling twice it's inconsistent to checking this need, a new event that is triggered only when the query was executed would be good.
Beta Was this translation helpful? Give feedback.
All reactions
-
@JoaoHamerski Dunno its too late. But Did you tried with debounce option?
debounce: 100,
query: ME_QUERY,
result(res) {
console.log({ res });
},
Sometimes this stops calling api twice.
Beta Was this translation helpful? Give feedback.
All reactions
-
I'm having this issue too, where it doesn't matter what I set fetchPolicy to, and even returnpartialData: false doesn't help (both in the ApolloClient constructor, and the UseQuery variables).
OnResult will keep returning partial data that I now have to filter out.
Beta Was this translation helpful? Give feedback.