Apollo-client: fetchPolicy "cache-and-network" forced to refetch after unrelated query finishes

Created on 24 Sep 2020  路  7Comments  路  Source: apollographql/apollo-client

The application initializes:

  • Subscribes to a watchQuery() with fetchPolicy "cache-and-network" and waits for a response
  • Creates other unrelated plain query() and quickly receives the response

Intended outcome:
I would expect apollo client to process the response of query() and keep waiting for the first watchQuery result.

Actual outcome:
The plain query sends a notification that triggers a reobserve in the watchQuery, which makes a refetch.

Step by step

Plain query finishes, calls stopQuery()
https://github.com/apollographql/apollo-client/blob/bd778d17411863bcefbb3302befe8ae6c3276e44/src/core/QueryManager.ts#L494

Which makes a broadcast to all queries
https://github.com/apollographql/apollo-client/blob/bd778d17411863bcefbb3302befe8ae6c3276e44/src/core/QueryManager.ts#L653

watchQuery thinks it should be notified in shouldNotify
https://github.com/apollographql/apollo-client/blob/bd778d17411863bcefbb3302befe8ae6c3276e44/src/core/QueryInfo.ts#L209-L214

Previously, watchQuery created a listener and it's now called.
https://github.com/apollographql/apollo-client/blob/bd778d17411863bcefbb3302befe8ae6c3276e44/src/core/QueryInfo.ts#L183

reobserve() then makes watchQuery to refetch again

Versions
3.2.0

Most helpful comment

Here is a repro
The bug is introduced somewhere between these two versions: https://github.com/apollographql/apollo-client/compare/v3.1.0-pre.3...v3.1.0-pre.4

Of those commits only this one looks relevant: https://github.com/apollographql/apollo-client/commit/1cd1df9b6aa3c70eed6ddc378451c7f9cc79514a

Sure enough, adding nextFetchPolicy: 'cache-first' to my query solves the issue and seems like a reasonable workaround.

All 7 comments

Is there any workaround for this issue? Maybe you could call refetch in an effect to emulate how cache-and-network normally behaves?

@joshjg I don't know if you refer to ObservableQuery.refetch or mutate(, { refetchQueries }), but both work in a similar way. In my opinion refetchQueries scales better.

cache-first in watchQuery + manual refetchQueries in mutations should suffice as a workaround. Note however that it involves quite a lot of work.

First, for every watchQuery you have to store the query and variables somewhere. Second, every time the variables of a watchQuery are updated, the stored refetchQuery must be updated. Finally you have to decide which refetchQueries should be passed to each mutation. If anyone modifies a query or a mutation, they should rethink again which refetchQueries to pass.

@javier-garcia-meteologica That's a good idea, but what about cases such as "reloading the page"?
Like, if you reload the page, the apollo cache is lost. Thus, each query now is useless if it only uses cache-first, because it requires a mutation for it to get data from the network/backend.

Unless, I dont understand very well the issue, for which I would like to apologize. :P Feel free to correct me if that's the case. :)

@exapsy cache-first should automatically make network requests if and only if it doesn't find suitable data in cache.

Ah yeah you're right. I'm sorry, it was a long night and totally I misread that!
Which makes it a great idea. Thank you!

@benjamn I noticed that #6891 actually mitigates this issue (at least in my case) - however, that commit was later reverted.

Here is a repro
The bug is introduced somewhere between these two versions: https://github.com/apollographql/apollo-client/compare/v3.1.0-pre.3...v3.1.0-pre.4

Of those commits only this one looks relevant: https://github.com/apollographql/apollo-client/commit/1cd1df9b6aa3c70eed6ddc378451c7f9cc79514a

Sure enough, adding nextFetchPolicy: 'cache-first' to my query solves the issue and seems like a reasonable workaround.

Was this page helpful?
0 / 5 - 0 ratings