browser-cachevue-composition-apivue-apollographql-mutation

Update cache after delete mutation Apollo vue


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


Solution

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