apollo-client
apollo-client copied to clipboard
watchQuery with "network-only" policy does not fire when optimistic data is written to cache
Hello. I subscribe to watchQuery with "network-only" policy. Then I execute a mutation with optimisticData and make use of update function to fill the cache with optimistic data. On the second invocation of the update function I update the cache with server data. It works like a charm with fetch poilicy "cache-first" for example. But it does not work with "network-only" because in this case watchQuery fires only once - when server responses. I wonder if this is an expected behaviour. I thought watchQuery would fire twice - whenever cache is updated.
Hi @vadim-loginov!
Generally, it is expected behaviour that with "network-only"
, you will not receive any updates from the cache before your initial network request has succeeded.
From your description, I'm not entirely sure if that's the case here, though - could you please clarify that?
Do you just not get these updates in the beginning, or for a longer period of time?
Also, how do you invoke the watchQuery
and the mutation?
Hi @phryneas! Thank you for your response.
I use Angular
and apollo-angular
. Here is how watchQuery
is used:
ngOnInit() {
this.qRef = this.apollo.watchQuery({
query: booksQuery,
fetchPolicy: "network-only"
});
this.qRef.valueChanges.subscribe(({ data }) => {
this.books = data.books || [];
console.log("watchQuery fired");
});
}
Here is the mutation:
addBook() {
console.log("addBook called");
const newBook = {
// not important
};
this.apollo.mutate({
mutation: gql`
mutation AddBook($id: ID, $title: String, $author: String) {
addBook(id: $id, title: $title, author: $author) {
id
__typename
title
}
}
`,
variables: {
id: newBook.id,
title: newBook.title,
author: newBook.author.name,
},
optimisticResponse: { addBook: newBook },
update(cache, result) {
console.log("update called")
const book: Book | undefined = result.data?.addBook;
if (!book) {
return;
}
cache.modify({
fields: {
books(cachedBooks, { readField }) {
if (cachedBooks.some((cachedBook: any) => readField('id', cachedBook) === book.id)) {
return cachedBooks;
}
return cachedBooks.concat(book);
}
}
})
},
}).subscribe(({ data }) => {
console.log("mutation completed");
});
}
So. Update function mutates cache twice per mutation invocation whereas watchQuery fires (I see "watchQuery fired"
in console) only once per invocation. It goes like this:
addBook called
update called <- optimistic
[waiting for the server..]
update called <- real data
watchQuery fired
mutation completed
...
addBook called
update called <- optimistic
[waiting for the server..]
update called <- real data
watchQuery fired
mutation completed
etc.
But if I use "cache-and-network"
it goes differently:
addBook called
update called <- optimistic
*********************
* watchQuery fired *
*********************
[waiting for the server..]
update called <- real data
watchQuery fired
mutation completed
...
addBook called
update called <- optimistic
*********************
* watchQuery fired *
*********************
[waiting for the server..]
update called <- real data
watchQuery fired
mutation completed
etc.
watchQuery is fired twice per mutation - every time the cache is modified in update
function.