如何在多种类型上使用GraphQL片段 [英] How to use GraphQL fragment on multiple types

查看:20
本文介绍了如何在多种类型上使用GraphQL片段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Gatsby项目,它对两种不同类型的内容进行了非常相似的GraphQL查询:常规页面和维基文章。

分页

export const query = graphql`
  query($slug: String!) {
    page: contentfulPage(slug: {eq: $slug}) {
      title
      slug
      body {
        remark: childMarkdownRemark {
          excerpt
          html
          headings {
            value
            depth
          }
        }
      }
      updatedAt(formatString: "D. MMM YYYY")
      authors {
        name
        email
      }
    }
  }
`

插件的Wiki文章

export const query = graphql`
  query($slug: String!) {
    article: contentfulWikiArticle(slug: {eq: $slug}) {
      title
      slug
      body {
        remark: childMarkdownRemark {
          excerpt
          html
          headings {
            value
            depth
          }
        }
      }
      updatedAt(formatString: "D. MMM YYYY")
      authors {
        name
        email
      }
 +    section {
 +      title
 +      slug
 +    }
 +    subsection {
 +      title
 +      slug
 +    }
    }
  }
`

除了Wiki文章的附加部分和小节外,查询都是相同的。为了保持干爽,我如何将页面字段移动到一个单独的片段中,该片段也可以扩展到wiki文章查询中,尽管它们的类型不同?GraphQL是否可以提供如下内容:

fragment pageFields on [ContenfulPage, ContenfulWikiArticle] {
  ...
}

推荐答案

Gatsby recent release允许用户为图形QL架构设置自己的类型,最终使此问题成为可能。

如果用户拥有架构的控制权,使用GraphQL始终是可能的,但由于最近的Gatsby更新,用户最终可以自己实现这一点。

安装

为了设置一个简单的示例,我将在这样一个简单的文件夹上使用gatsby-transformer-json

jsonFolder
  |--one.json { "type": "One", "name": "a", "food": "pizza" }
  `--two.json { "type": "Two", "name": "b", "game": "chess" }

并使用选项声明我的类型名称:

{
  resolve: `gatsby-transformer-json`,
  options: { 
    typeName: ({ object }) => object.type,
  },
},

现在我有两个为我创建的类型。我可以在其中一个上创建片段,但不能两个都创建:

export const name = graphql`
  fragment name on One {
    name
  }
`

export const pageQuery = graphql`
  query {
    one {
      ...name
    }
    two {
      ...name <-- ⚠️ throw type error
    }
  }
`

让我们解决这个问题。

设置类型

我将使用一个名为createTypes的新API注册一个新接口&为每个json注册两种类型。请注意,JsonNode包含OneTwo的公共字段:

exports.sourceNodes = ({ actions }) => {
  const { createTypes } = actions
  const typeDefs = `
    interface JsonNode {
      name: String
      type: String!
    }

    type One implements Node & JsonNode {
      name: String
      type: String!
      food: String
    }

    type Two implements Node & JsonNode {
      name: String
      type: String!
      game: String
    }
  `
  createTypes(typeDefs)
}

神奇之处在于这一行,One&;Two同时实现了JsonNode(自定义接口)和Node(Gatsby接口)。

type One implements Node & JsonNode { ... }

现在我可以编写实现JsonNode&;的片段了。它对两种类型都有效。

// blogPostTemplate.js
import React from "react"
import { graphql } from "gatsby"

export default ({ data }) => <div>{JSON.Stringify(data)}</div>

export const name = graphql`
  fragment name on JsonNode {
    name
    level
  }
`

export const pageQuery = graphql`
  query {
    one {
      ...name <- 👍 works
    }
    two {
      ...name <- 👍 works
    }
  }
`

这需要一些设置,但如果您事先知道您的数据类型,可能是值得的,而且需要大量重复使用片段。

这篇关于如何在多种类型上使用GraphQL片段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆