【问题标题】:How to generate the same graphql query with different fields如何使用不同的字段生成相同的 graphql 查询
【发布时间】:2019-07-05 06:57:39
【问题描述】:

我正在使用graphql-tag,所以我将使用该语法。

假设我有这个查询:

const query = gql`
 query user(id: String) {
  user(id: $id) {
   id
  }
 }
`

如果在不同的调用中,除了id 之外,我还想要字段usernameemail,而无需再次重写整个查询,那么重用同一个查询文档节点的最佳模式是什么:

const query = gql`
 query user(id: String) {
  user(id: $id) {
   id
   username
   email
  }
 }
`

我在前端使用react-apollo,如果这让事情变得更有趣的话。

编辑:

只是为了澄清......这样的事情

const userIdFrag = gql`
  fragment UserId on User {
    id
  }
`

const fullUserFrag = gql`
  fragment FullUser on User {
    id
    username
    email
  }
`

const generateQuery = (documentNode) => {
  return gql`
   query user(id: String) {
      user(id: $id) {
       ...documentNode
      }
     }
     ${documentNode}
  `
}

const idQuery = generateQuery(userIdFrag);
const fullUserQuery = generateQuery(fullUserFrag);

(上述方法确实有效,但控制台中的 graphql 出现错误,这让我相信这不是我应该做的事情)

【问题讨论】:

  • 您可以查看片段 - apollographql.com/docs/react/advanced/fragments.html,尽管您仍然需要定义查询 2 次​​span>
  • 是的,我知道片段,我想知道是否有更好的方法可以避免每次都写查询签名
  • 您遇到的错误是什么?
  • @ric0 错误基本上说“在 graphql 查询中未使用 documentNode”,即使 ${documentNode} 片段正在添加到其中

标签: graphql react-apollo apollo-client


【解决方案1】:

根据您的评论,以下应该有效:


const generateQuery = (documentNode, fragment) => {
  return gql`
   query user(id: String) {
      user(id: $id) {
       ...${fragment}
      }
     }
     ${documentNode}
  `
}

const idQuery = generateQuery(userIdFrag, 'UserId');
const fullUserQuery = generateQuery(fullUserFrag, 'FullUser');

基本上使用的片段名称是实际需要传播的片段名称,而整个 documentNode 对象放在最后,在查询的右括号之后

【讨论】:

  • 这很有效,现在我看到它写出来了,这更有意义。我可能会做出的一项更改是,您实际上可以从位于...的 documentNode 获取片段的名称。node.definitions[0].name.value
  • 是的,当然。我没想到,你的方式更有效。
【解决方案2】:

我不是该主题的专家,但这是我能够找到的。 (如果您发现我的假设有任何错误,请告诉我)。

我发现this article 对动态生成gql 查询/突变有一些好处。使用静态方法似乎可以获得一些不错的好处,尽管它需要更多的输入。

但是,如果您确实需要动态字段,我找不到任何关于使用 GraphQL 提供的 @skip 指令的坏处。 Here the docs ref.

对于在react-apollothey also have it in their docs中使用的情况。

因此,您的代码最终可能看起来像这样:

const query = gql`
 query user($id: String, $skipUserMeta: Boolean!) {
  user(id: $id) {
   id
   username @skip(if: $skipUserMeta)
   email @skip(if: $skipUserMeta)
  }
 }
`

您只需将skipUserMeta 作为变量传递到id 字段旁边。

注意:我实际上找到了一个关于the exact same approach here的视频

【讨论】:

    猜你喜欢
    • 2019-07-23
    • 2020-07-02
    • 2022-11-19
    • 2019-07-30
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 2020-04-13
    相关资源
    最近更新 更多