Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Query result called twice #492

Unanswered
adamalfredsson asked this question in Q&A
Discussion options

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.

You must be logged in to vote

Replies: 25 comments 2 replies

Comment options

@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!

You must be logged in to vote
0 replies
Comment options

@nomadoda I believe that the first response is the result you get from the cache.

You must be logged in to vote
0 replies
Comment options

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'
 }
})
You must be logged in to vote
0 replies
Comment options

Ok, that makes sense. Is there any hook called once, when the query is finished?

You must be logged in to vote
0 replies
Comment options

I have the same issue. It's definitely cache related. The Apollo Component only calls result once so this behavior is confusing.

You must be logged in to vote
0 replies
Comment options

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

You must be logged in to vote
0 replies
Comment options

Did someone find a solution?

You must be logged in to vote
0 replies
Comment options

fectchPolice: 'no-cache' works but loading will be always false, network-only doesn't work.

You must be logged in to vote
0 replies
Comment options

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.

You must be logged in to vote
0 replies
Comment options

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

You must be logged in to vote
0 replies
Comment options

Hi everyone, there any update about this issue?
Thanks in advance

You must be logged in to vote
0 replies
Comment options

no update here?
I count the same issue

You must be logged in to vote
0 replies
Comment options

The same...Any results?

You must be logged in to vote
0 replies
Comment options

@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

You must be logged in to vote
0 replies
Comment options

I don’t think so, I’m afraid
...
On 16 Nov 2020, at 19:07, Evgen ***@***.***> wrote: @nomadoda <https://github.com/nomadoda> , did you solve this issue? — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <https://github.com/vuejs/vue-apollo/issues/492#issuecomment-728231867>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AGFS5SVPA7ACS5DQ65QYDZTSQFS7XANCNFSM4GREOJTQ>.
You must be logged in to vote
0 replies
Comment options

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.

You must be logged in to vote
0 replies
Comment options

This is still ocurring for me even with network-only (see comment above for config).

You must be logged in to vote
0 replies
Comment options

Then my explanation is clearly wrong. But I would still guess that there is something going on at the cache layer that is driving this. If you change the applications's *global* fetch policy (the default) to "Network only", do you still get two callbacks? And does the first callback actually have any objects in it, or is it null?
...
On Fri, Nov 27, 2020 at 4:33 PM Kendall Roth ***@***.***> wrote: This is still ocurring for me even with network-only (see comment above for config). — You are receiving this because you commented. Reply to this email directly, view it on GitHub <https://github.com/vuejs/vue-apollo/issues/492#issuecomment-735018247>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AEJX3CW6QIXIOCQ7AATJOBTSSBAL3ANCNFSM4GREOJTQ> .
You must be logged in to vote
0 replies
Comment options

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?

You must be logged in to vote
0 replies
Comment options

@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.

You must be logged in to vote
0 replies
Comment options

@NataliaTepluhina , very nice! Thanx a lot!

You must be logged in to vote
0 replies
Comment options

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?

You must be logged in to vote
1 reply
Comment options

An apollo query result can be emitted with { loading: true, ... }

Comment options

@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.

You must be logged in to vote
0 replies
Comment options

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.

You must be logged in to vote
1 reply
Comment options

@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.

Comment options

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.

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

AltStyle によって変換されたページ (->オリジナル) /