变异后自动更新apollo客户端缓存不影响现有查询[英] Auto-update of apollo client cache after mutation not affecting existing queries

本文是小编为大家收集整理的关于变异后自动更新apollo客户端缓存不影响现有查询的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我有一个突变(上载T​​ransaction),返回某些名为Transaction的对象的某些列表.

#import "TransactionFields.gql" 
mutation UploadTransaction($files: [Upload!]!) {
  uploadFile(files: $files){
    transactions {
      ...TransactionFields
    }
  }
}

从后端返回的事务(石墨烯)具有ID和TypeName字段.因此,它应该自动更新缓存中的交易.在Apollo的Chrome Dev工具中,我可以看到新的交易:

在此处输入图像说明

我也有一个查询gettransactions获取所有事务对象.

#import "TransactionFields.gql"
query GetTransactions {
  transactions {
    ...TransactionFields
  }
}

但是,我看不到查询返回新添加的交易.在初始加载期间,Apollo客户端加载了292件交易,并在root_query下显示.它不断返回相同的292笔交易. uploadTransaction突变添加开发工具中的"交易"类型"事务"的新对象,而不会影响Dev-tools中的root_query或我在代码中的我的查询.

在此处输入图像说明

transactionfields.gql是

fragment TransactionFields on Transaction {
    id
    timestamp
    description
    amount
    category {
      id
      name
    }
    currency
}

知道我在做什么错?我是Apollo客户端的新手和GraphQl

推荐答案

来自

  • 无法知道插入,删除或更新用户应该更新特定查询.您的查询可能适用于所有名称" Bob"的用户 - 如果您创建了名称为" Susan"的用户,则不应更新查询以反映该添加.同样,如果一个突变更新用户,则需要更新查询以反映更改.它是否最终应该归结为只有您的服务器知道的业务规则.
  • 因此,为了更新缓存,您有两个选项:

    使用文档中使用update的示例:

    update (cache, { data: { addTodo } }) {
      const { todos } = cache.readQuery({ query: GET_TODOS });
      cache.writeQuery({
        query: GET_TODOS,
        data: { todos: todos.concat([addTodo]) },
      });
    }
    

    阅读文档以获取其他详细信息.

    本文地址:https://www.itbaoku.cn/post/1938120.html

    问题描述

    I have a mutation (UploadTransaction) returning certain list of certain object named Transaction.

    #import "TransactionFields.gql" 
    mutation UploadTransaction($files: [Upload!]!) {
      uploadFile(files: $files){
        transactions {
          ...TransactionFields
        }
      }
    }
    

    Transaction returned from backend (graphene) has id and typename field. Hence it should automatically update Transaction in the cache. In chrome dev tools for Apollo, I can see new transactions:

    enter image description here

    I also have a query GetTransactions fetching all Transaction objects.

    #import "TransactionFields.gql"
    query GetTransactions {
      transactions {
        ...TransactionFields
      }
    }
    

    However I don't see newly added Transaction being returned by the query. During initial load, Apollo client loaded 292 transactions which it shows under ROOT_QUERY. It keeps returning same 292 transactions. UploadTransaction mutation add new object of type "Transaction" in cache in dev-tools without affecting ROOT_QUERY in dev-tools or my query in code.

    enter image description here

    TransactionFields.gql is

    fragment TransactionFields on Transaction {
        id
        timestamp
        description
        amount
        category {
          id
          name
        }
        currency
    }
    

    Any idea what am I doing wrong? I am new to apollo client and graphql

    推荐答案

    From the docs:

    If a mutation updates a single existing entity, Apollo Client can automatically update that entity's value in its cache when the mutation returns. To do so, the mutation must return the id of the modified entity, along with the values of the fields that were modified. Conveniently, mutations do this by default in Apollo Client...

    If a mutation modifies multiple entities, or if it creates or deletes entities, the Apollo Client cache is not automatically updated to reflect the result of the mutation. To resolve this, your call to useMutation can include an update function.

    If you have a query that returns a list of entities (for example, users) and then create or delete a user, Apollo has no way of knowing that the list should be updated to reflect your mutation. The reason for this is two fold

    • There's no way for Apollo to know what a mutation is actually doing. All it knows is what fields you are requesting and what arguments you are passing those fields. We might assume that a mutation that includes words like "insert" or "create" is inserting something on the backend but that's not a given.
    • There's no way to know that inserting, deleting or updating a user should update a particular query. Your query might be for all users with the name "Bob" -- if you create a user with the name "Susan", the query shouldn't be updated to reflect that addition. Similarly, if a mutation updates a user, the query might need to be updated to reflect the change. Whether it should or not ultimately boils down to business rules that only your server knows about.

    So, in order to update the cache, you have two options:

    • Trigger a refetch of the relevant queries. You can do this by either passing a refetchQueries option to your useMutation hook, or by manually calling refetch on those queries. Since this requires one or more additional requests to your server, it's the slower and more expensive option but can be the right option when A) you don't want to inject a bunch of business logic into your client or B) the updates to the cache are complicated and extensive.
    • Provide an update function to your useMutation hook that tells Apollo how to update the cache based on the results of the mutation. This saves you from making any additional requests, but does mean you have to duplicate some business logic between your server and your client.

    The example of using update from the docs:

    update (cache, { data: { addTodo } }) {
      const { todos } = cache.readQuery({ query: GET_TODOS });
      cache.writeQuery({
        query: GET_TODOS,
        data: { todos: todos.concat([addTodo]) },
      });
    }
    

    Read the docs for additional details.