何时使用Apollo的cacheRedirects?

问题描述 投票:1回答:2

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

它给出了一个例子:

在某些情况下,查询以不同的密钥请求客户端存储中已存在的数据。一个非常常见的例子是当您的UI具有列表视图和详细视图时,它们都使用相同的数据。列表视图可能会运行以下查询:

查询ListView {books {id title abstract}}

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

查询DetailView {book(id:$ id){id title abstract}}

我们知道数据很可能已经存在于客户端缓存中,但由于它是通过不同的查询请求的,因此Apollo Client不知道这一点。为了告诉Apollo Client在哪里查找数据,我们可以定义自定义解析器

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

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

ApolloClient究竟在哪种情况下无法解决这个问题,为什么呢?

apollo apollo-client
2个回答
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提供了一种说法“此查询将返回此特定类型”的方法,而不会首先触发查询。


0
投票

只是事后的想法:这本质上是由于GraphQL设计。在GraphQL中,book(id)它的解析器可以任意方式自由地解释id。它只是一个带有单个参数的函数调用,它恰好返回Book类型的实例。

GraphQL实际上没有任何关于ID的内容。它只承认__typename特殊。

只有Relay,在某种程度上Apollo,稍后会添加一个对象ID的概念。他们采用了一种不同的方法,使用Relay强制将GraphQL架构转换为更严格的正式结构。

关于架构不可用于客户端甚至还有额外的复杂性(另一个答案也提到)(因此客户端甚至不知道book将返回Book而不进行查询)。这再次遵循GraphQL规范。

© www.soinside.com 2019 - 2024. All rights reserved.