How do I update the cache for a query after a graphql mutation in Vue3 using the Composition Api? I have my vue setup in main.js like this:
import { createApp, provide, h } from "vue"
import App from "./App.vue"
import router from "./router";
import { InMemoryCache, HttpLink, ApolloClient } from "@apollo/client";
import { DefaultApolloClient } from '@vue/apollo-composable';
const apClient = new ApolloClient({
cache: new InMemoryCache({ addTypename: false }),
link: new HttpLink({ uri: 'http://localhost:8000/graphql' }),
});
const app =createApp({
setup() {
provide(DefaultApolloClient, apClient);
},
render: () => h(App),
});
app.use(router)
.mount('#app')
My graphql query looks like this:
query getMatters($id:ID, $client:ID) {
Matters(client:$client, id:$id) {
client {
id
name
}
category
id
title
status
}
}
The results look like this:
{
"data": {
"Matters": [
{
"category": "Game",
"id": "2",
"title": "Clown and clown",
"status": "Open",
},
{
"category": "Players",
"id": "3",
"title": "Second thing",
"status": null,
},
{
"category": "Game",
"id": "4",
"title": "Jacks",
"status": "Open",
},
{
"category": "Game",
"id": "5",
"title": "aaa",
"status": null,
},
"category": "Game",
"id": "6",
"title": "fff",
"status": null,
}
]
}
}
Delete mutation
mutation deleteMatter($input:[MatterUpdate] ){
DeleteMatter(input: $input) {
success
errors
}
}
The delete function here works but for updating the cache I tried:
const { mutate: deleteResult } = useMutation(deleteMatter, () =>({
variables: {"input": {"id": matter.value.id},
}, update: (cache) => {
cache.evict({ id: cache.identify({ __typename: 'Matter', id: matter.value.id }) });
cache.gc();
},
}))
But it did not refresh in the browser. I also tried:
const { mutate: deleteResult } = useMutation(deleteMatter, () =>({
variables: {"input": {"id": matter.value.id},
}, update: (cache) => {
let data = cache.readQuery({query: getMatters, variables: {
client: id.value}})
const matterlist = data.matters.filter((t) => (t.id !== matter.value.id))
cache.writeQuery({query: getMatters, data: {matters: matterlist}})
}
}))
but got an error Uncaught (in promise) Error: data.matters is undefined
Also tried:
deleteResult({"input": {"id": matter.value.id},
}, {update: (cache) => {
let data = cache.readQuery({query: getMatters, variables: {
client: id.value}})
const currentItem = data.Matters.find(item => item.id === matter.value.id)
data.Matters.splice(data.Matters.indexOf(currentItem), 1);
cache.writeQuery({query: getMatters, data, variables:{client: id.value}})
}})
But got the error Uncaught (in promise) Error: property 2 is non-configurable and can't be deleted
after a long search I was able to find a solution that works (at least in my case !!). I used Vue-3 with composition API. My deleteBook.mutation.gql query file for delete is :
mutation DeleteBook($id: ID!) {
deleteBook(id: $id)
}
in my template the delete action by a click on a button is (i used Bootstrap too): ...
<button class="btn btn-sm btn-danger ms-2" @click="onDeleteClicked(book.id)">
Delete book
</button>
in my script section:
import DELETE_BOOK_MUTATION from "@/graphql/deleteBook.mutation.gql";
import { useMutation } from "@vue/apollo-composable";
let bookToDelete = ref("");
const onDeleteClicked = (item) => {
bookToDelete.value = item;
deleteBook();
};
const { mutate: deleteBook, onDone } = useMutation(DELETE_BOOK_MUTATION, () => ({
variables: {
id: bookToDelete.value,
},
update(cache) {
const normalizedId = cache.evict({
id: cache.identify({ id: bookToDelete.value, __typename: "Book" }),
});
cache.gc();
console.log("normalizedId: ", normalizedId);
},
}));
onDone(() => console.log("Updated cache: ", result));
In this way the query works, the browser is automatically refreshed ad there is no warning or error in the devtools!!! I hope this has been helpful to you!