何时使用Apollo的cacheRedirects?

时间:2018-10-22 10:36:04

标签: apollo apollo-client

Apollo文档discusses the use of cacheRedirects告诉Apollo如何通过其他查询访问缓存中已存在的数据。

它给出了一个例子:

  

在某些情况下,查询会请求客户端中已经存在的数据   使用其他密钥存储。一个很常见的例子是   您的用户界面具有使用相同数据的列表视图和详细信息视图。   列表视图可能会运行以下查询:

     

query ListView {图书{       ID       标题       摘要}}

     

选择特定书籍后,详细信息视图会显示一个   使用此查询的单个项目:

     

查询DetailView {图书(id:$ id){       ID       标题       摘要}}

     

我们知道数据很可能已经在客户端缓存中,但是   因为是通过其他查询请求的,所以Apollo Client不会   我知道。为了告诉Apollo Client在哪里寻找数据,   我们可以定义自定义解析器

我试图理解为什么对于本示例来说这是必需的。如果books查询返回的类型为Book的数组,并且book请求返回的类型为Book的单个对象,则肯定归一化的高速缓存将已经具有每个数据(来自ListView查询)基于类型名称和ID的书籍,DetailView查询可以直接使用该信息,而无需任何进一步干预。相反,我们被告知编写一些代码来帮助它:

const cache = new InMemoryCache({
  cacheRedirects: {
    Query: {
      book: (_, args, { getCacheKey }) =>
        getCacheKey({ __typename: 'Book', id: args.id })
    },
  },
});

究竟是什么情况下ApolloClient无法自行解决?为什么?

2 个答案:

答案 0 :(得分:2)

显而易见,直观的是,像下面这样的查询,我们通过其Book属性来获取单个id对象。

query DetailView($id: ID) {
  book(id: $id) {
    id
    title
    abstract
  }
}

但是,在此示例中,此处的参数名称(id恰好与高速缓存使用的属性的名称(id)相匹配。除非另有约定,否则没有什么说法不能将参数本身称为bookIdbookIDsupercalifragilisticexpialidocious。即使查询返回Book类型并接受一个或多个参数,Apollo也无法推断哪个参数实际上是缓存规范化中使用的ID。同样,如果存在其他参数,则在是否可以使用当前缓存的内容方面,它们可能无关紧要-尚需进一步的逻辑才能确定。

这里的另一个考虑是,除了有选择地将IntrospectionFragmentMatcher的实例传递给您的InMemoryCache外,Apollo实际上并不知道所查询的端点的模式是什么。 之后,使用__typename属性获取查询后,确定缓存中归一化使用的类型。 cacheRedirects的全部要点是,如果一项或多项已在缓存中,则可以防止触发查询。但是,给定特定查询,Apollo无法知道它将返回特定类型,直到该查询返回。 cacheRedirects提供了一种方式来表示“此查询将返回此特定类型”,而无需首先触发查询。

答案 1 :(得分:0)

只是事后的想法:这本质上是由于GraphQL设计所致。在GraphQL中,book(id)的解析器可以随意使用自己喜欢的任何方式来解释id。这只是一个带有单个参数的函数调用,碰巧会返回一个Book类型的实例。

GraphQL实际上什么也没说。它仅将__typename识别为特殊字符。

仅中继,并且在某种程度上是Apollo,稍后再添加对象ID的概念。但是,它们采取了一些不同的方法,其中Relay将您的GraphQL模式强制为一个更严格的正式结构。

对于客户机不可用的架构,甚至还有其他复杂性(也由其他答案提到)(客户机甚至不知道book将不进行查询就返回Book)。再次遵循GraphQL规范。