React Apollo updating client cache after mutation

巧了我就是萌 提交于 2021-01-28 07:44:34

问题


I am trying to update my chache after succesfully executing a mutation. Here is my query and mutation:

export const Dojo_QUERY = gql`
query Dojo($id: Int!){
  dojo(id: $id){
    id,
    name,
    logoUrl,
    location {
     id,
     city,
     country
    },
    members{
      id
    },
    disziplines{
      id,
      name
    }
  } 
}`;


export const addDiszipline_MUTATION = gql`
mutation createDisziplin($input:DisziplineInput!,$dojoId:Int!){
  createDisziplin(input:$input,dojoId:$dojoId){
    disziplin{
     name,
     id
    }
  }
}`;

and my mutation call:

const [createDisziplin] = useMutation(Constants.addDiszipline_MUTATION,
    {
      update(cache, { data: { createDisziplin } }) {
        console.log(cache)
        const { disziplines } = cache.readQuery({ query: Constants.Dojo_QUERY,variables: {id}});
        console.log(disziplines)
        cache.writeQuery({
        ...some update logic (craches in line above)
        });
      }
    }
    );

when i execute this mutation i get the error

Invariant Violation: "Can't find field dojo({"id":1}) on object {
  "dojo({\"id\":\"1\"})": {
    "type": "id",
    "generated": false,
    "id": "DojoType:1",
    "typename": "DojoType"
  }
}."

In my client cache i can see

data{data{DojoType {...WITH ALL DATA INSIDE APPART FROM THE NEW DISZIPLINE}}

and

data{data{DisziplineType {THE NEW OBJECT}}

There seems to be a lot of confusion around the client cache around the web. Somehow none of the posed solutions helped, or made any sense to me. Any help would be greatly appreciated.

EDIT 1: Maybe this can help?

ROOT_QUERY: {…}
"dojo({\"id\":\"1\"})": {…}​​​​​
generated: false​​​​​
id: "DojoType:1"​​​​​
type: "id"​​​​​
typename: "DojoType"​​​​​
<prototype>: Object { … }​​​​
<prototype>: Object { … }

Edit 2

I have taken Herku advice and started using fragment. however it still seems to not quite work.

My udated code:

 const [createDisziplin] = useMutation(Constants.addDiszipline_MUTATION,
    {
      update(cache, { data: { createDisziplin } }) {
        console.log(cache)
        const { dojo } = cache.readFragment(
          { fragment: Constants.Diszilines_FRAGMENT,
            id:"DojoType:"+id.toString()});
        console.log(dojo)
      }
    }
    );

with

export const Diszilines_FRAGMENT=gql`
  fragment currentDojo on Dojo{
    id,
    name,
    disziplines{
      id,
      name
    }
  }
`;

however the result from console.log(dojo) is still undefined.Any advice?


回答1:


So I think your actual error is that you have to supply the ID as as a string: variables: {id: id.toString()}. You can see that these two lines are different:

dojo({\"id\":1})
dojo({\"id\":\"1\"})

But I would highly suggest to use readFragment instead of readQuery and update the dojo with the ID supplied. This should update the query as well and all other occurrences of the dojo in all your queries. You can find documentation on readFragment here.

Another trick is as well to simply return the whole dojo in the response of the mutation. I would say people should be less afraid of that and not do to much cache updates because cache updates are implicit behaviour of your API that is nowhere in your type system. That the new disziplin can be found in the disziplins field is now encoded in your frontend. Imagine you want to add another step here where new disziplins have to be approved first before they end up in there. If the mutation returns the whole dojo a simple backend change would do the job and your clients don't have to be aware of that behaviour.



来源:https://stackoverflow.com/questions/58255167/react-apollo-updating-client-cache-after-mutation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!