【问题标题】:Apollo Client erroneously reads from cache when it should make network requestApollo 客户端在应该发出网络请求时错误地从缓存中读取
【发布时间】:2021-04-22 23:55:42
【问题描述】:

我有一系列 Apollo 查询,其工作方式如下:

  • 可以进行查询以从特定的Website 检索子资源
  • Apollo 服务器不是将 Website ID 作为输入参数传递,而是从 HTTP 标头或 cookie 中检索 ID。
  • 因此查询看起来像这样:
query {
  currentWebsite {
    id
    ...sub-resources
  }
}

在当前网站更改之前,此方法运行良好。这是因为 Apollo 客户端已经在缓存中有一个网站,并且会从缓存中检索第一个(并且不正确的)网站,而不是发出另一个 HTTP 请求。我相信这是因为查询不包含唯一 ID,因此它将所有 currentWebsite 查询视为相同。

现在我知道有很多方法可以解决这个问题。以下是我知道的方法,以及感知到的缺点:

  1. 更新 Apollo 服务器以允许接收 websiteId 作为输入参数。我对此进行了测试,并且可以正常工作。不幸的是,更新 API 需要做很多工作。
  2. fetchPolicy 从默认值更改为cache-and-network。这是一个快速修复,但会发出比它需要的更多的 HTTP 请求。
  3. 网站更改时手动使部分缓存无效。这是我最不喜欢的解决方案。
  4. 从缓存中手动读取。如果查询不存在,请使用类似network-only 的字段策略调用useQuery。这感觉非常沉重。

最终,我认为这些解决方案中的任何一个都不是我所需要的。我觉得必须有一种方法为 Apollo 缓存每个查询的网站 ID,以便它可以自行确定是应该从缓存中检索网站还是获取新网站。我发现 Apollo 缓存相当不透明,不知道从哪里开始!

【问题讨论】:

    标签: apollo apollo-client apollo-cache-inmemory


    【解决方案1】:

    所以这里的诀窍是编写一个custom keyArgs function 并利用这样一个事实,即您可以拥有不传递给服务器的客户端变量:

    query GetWebsiteById($websiteId: String) {
      currentWebsite {
        id
        ...sub-resources
      }
    }
    

    当您执行查询时,将您拥有的任何标头值传递给$websiteId。然后你可以在keyArgs 函数中读取该变量。

    const createCache = () => new InMemoryCache({
      typePolicies: {
        Query: {
          fields: {
            currentWebsite: {
              keyArgs: (_, { variables }) => {
                if (variables?.websiteId == null) {
                  return 'currentWebsite';
                } else {
                  return `currentWebsite:${variables.websiteId}`;
                }
              }
            }
          }
        }
      }
    });
    

    现在它将使用自己的唯一 ID 将每个查询存储在缓存中:currentWebsite:1currentWebsite:2 等。

    【讨论】:

    • 正是我需要的!
    • 嗯,我可能已经超前了。执行此操作时 GraphqQL 验证失败,因为未使用 $websiteIdGraphQLError: Variable \"$websiteId\" is never used in operation
    • 嗯,这似乎是 Apollo 服务器的一个已知问题...github.com/apollographql/eslint-plugin-graphql/issues/19
    猜你喜欢
    • 2021-06-05
    • 2019-10-18
    • 2019-03-17
    • 2018-07-12
    • 2022-01-06
    • 2021-10-16
    • 2021-06-03
    • 2019-06-25
    • 2017-03-18
    相关资源
    最近更新 更多