Apollo Client使用相同的id和不同的值替换具有第一个对象的副本数组的对象数组

时间:2017-10-25 17:45:05

标签: javascript graphql apollo-client

我们的GraphQL服务器使用包含一组对象的数据来响应查询,每个对象共享相同的id和不同的值的不同值。例如,我们可能有一个类似于:

的数组
[
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 6 },
  { id: 123, name: 'foo', type: 'bar', cost: 7 },
  { id: 123, name: 'foo', type: 'bar', cost: 8 }
]

我们可以在“网络”选项卡中看到来自服务器的响应中包含正确的数据。但是,当它通过Apollo Client模块进行处理时,数组已经转换为可能如下所示:

[
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 }
]

基本上我们看到的是,如果数组中的所有对象共享id的相同值,则数组中的所有对象都将成为数组中第一个对象的副本。

这是Apollo Client的预期行为吗?我们认为它可能与不正确的缓存有关,但我们也想知道Apollo客户端是否认为具有相同id的后续数组成员是同一个对象。

2 个答案:

答案 0 :(得分:1)

看起来这是预期的行为。 Apollo客户端在id上进行标准化。

答案 1 :(得分:0)

正如另一个答案所暗示的那样,这是因为 Apollo 通过 ID 进行了标准化。有一个非常广泛的 article on the official blog 解释了它的基本原理以及底层机制。

简而言之,从 Apollo 的缓存中可以看出,您的对象数组包含同一个对象的 4 个实例(id 123)。同一个ID,同一个对象。

这对 Apollo 来说是一个公平的假设,但在您的情况下则不然。 你必须明确告诉 Apollo,这些确实是 4 种不同的项目,应该区别对待。

过去我们使用 dataIdFromObject,您可以看到 example here

今天,您将使用 typePolicieskeyfields

const cache = new InMemoryCache({
  typePolicies: {
    YourItem: {
      // Combine the fields that make your item unique
      keyFields: ['id', 'cost'],
    }
  },
});

Docs