【问题标题】:Apollo weirdly alters the query resultApollo 奇怪地改变了查询结果
【发布时间】:2019-08-10 21:09:04
【问题描述】:

我在 React Native 中使用 react-apollos Query-Component 从我的后端获取数据。

结果如下所示:

[
  {
    id: 1,
    name: 'US Election',
    parties: [
      {
        name: 'democrats',
        id: 4,
        pivot: {
          id: 3,
          answers: [
            {
              id: 13,
              question_id: 3,
              reason: 'Lorem ipsum',
              __typename: "Answer"
            },
            {
              id: 14,
              question_id: 5,
              reason: 'Lorem ipsum',
              __typename: "Answer"
            },
          ],
          __typename: "ElectionPartyPivot"
        },
        __typename: "Party"
      },
    ],
    __typename: "Election"
  },
  {
    id: 2,
    name: 'Another one',
    parties: [
      {
        name: 'democrats',
        id: 4,
        pivot: {
          id: 7,
          answers: [
            {
              id: 15,
              question_id: 7,
              reason: 'Lorem ipsum',
              __typename: "Answer"
            },
            {
              id: 18,
              question_id: 9,
              reason: 'Lorem ipsum',
              __typename: "Answer"
            },
          ],
          __typename: "ElectionPartyPivot"
        },
        __typename: "Party"
      },
    ],
    __typename: "Election"
  }
]

现在,当我console.log的结果,第二次选举“Another one”pivot来自第一个条目US Election

我认为这是因为 Apollo 内部正在进行规范化(因为双方的 ID 相同)但我不确定如何修复它,因此它不会正常化或正常化它正确.

编辑

我想出了这个解决方案,但它看起来很老套。我现在将选举 ID 与当事方一起获取,并在缓存中创建不同的标识符。我想知道这是否是一种好习惯?

const cache = new InMemoryCache({
  dataIdFromObject: object => {
    switch (object.__typename) {
      case 'Party': return `${object.election_id}:${object.id}`;
      default: return defaultDataIdFromObject(object);
    }
  }
});

const client = new ApolloClient({
  uri: config.apiUrl,
  cache
});

【问题讨论】:

    标签: javascript apollo react-apollo apollo-client


    【解决方案1】:

    是的,在这种情况下需要提供自定义 dataIdFromObject。您应该考虑使用 Party:${object.election_id}:${object.id} 作为键,以防将来有其他 Election 字段需要相同的处理。

    从根本上讲,这是架构设计方式的问题。 GraphQL 中有一个基本假设,即虽然 GraphQL 中的节点可能彼此之间存在关系,但它们也完全相互独立。也就是说,在同一个上下文中,同一个节点不应该根据响应中其他节点的存在与否来表示不同的数据。

    不幸的是,这正是这个响应的结构——我们有一个代表Party的节点,但它的字段根据它与另一个节点的关系而有所不同——Election

    有两种方法可以解决此类问题。一种方法是维护每个Party 的不同实例,每个Election 具有不同的ID。 Party 类型背后的底层数据模型不会在其生命周期中代表一个政党,而是仅在一次选举的背景下呈现一个政党。

    另一种方法是重组架构以更准确地表示节点之间的关系。例如,支持这种查询的架构:

    {
      elections {
        id
        name
        parties {
          id
          name
          # omit pivot field on Party type
        }
        # instead because pivots are related directly to elections, add this field
        pivots {
          id
          answers
          # because we may still care what party the pivot is associated with as well
          # we can add a party field to pivot to show that relationship
          party {
            id
            name
          }
        }
      }
    }
    

    【讨论】:

    • 感谢您提供如此详细而精彩的解释。我想我必须开始考虑我在 GraphQL 中的数据结构与我以前的数据结构有点不同!
    猜你喜欢
    • 2018-09-01
    • 2021-04-18
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多