首页 > 解决方案 > React Apollo 在突变后更新客户端缓存

问题描述

成功执行突变后,我正在尝试更新我的 chache。这是我的查询和突变:

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
    }
  }
}`;

和我的突变电话:

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)
        });
      }
    }
    );

当我执行这个突变时,我得到了错误

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

在我的客户端缓存中,我可以看到

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

data{data{DisziplineType {THE NEW OBJECT}}

Web 上的客户端缓存似乎存在很多混淆。不知何故,提出的解决方案都没有帮助,或者对我没有任何意义。任何帮助将不胜感激。

编辑1: 也许这可以帮助?

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

编辑 2

我接受了 Herku 的建议并开始使用 Fragment。但是它似乎仍然不太有效。

我更新的代码:

 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)
      }
    }
    );

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

但是结果console.log(dojo)仍然是未定义的。有什么建议吗?

标签: reactjsgraphqlapolloreact-apollo

解决方案


所以我认为您的实际错误是您必须将 ID 作为字符串提供:variables: {id: id.toString()}。你可以看到这两行是不同的:

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

但我强烈建议使用提供的 IDreadFragment代替readQuery并更新 dojo。这也应该更新查询以及所有查询中出现的所有其他 dojo。readFragment 您可以在此处找到文档。

另一个技巧也是简单地返回整个 dojo 以响应突变。我会说人们应该少担心这一点,并且不要做太多的缓存更新,因为缓存更新是你的 API 的隐式行为,在你的类型系统中没有。可以在该disziplins字段中找到新的 disziplin 现在已在您的前端编码。想象一下,您想在此处添加另一个步骤,其中必须先批准新的 disziplins 才能最终进入那里。如果突变返回整个道场,一个简单的后端更改就可以完成这项工作,您的客户不必知道这种行为。


推荐阅读