如何在多种类型上使用GraphQL片段



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

按段塞分页

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
}
}
}
`

slug的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最近发布的版本允许用户为graphql模式设置自己的类型,从而使这个问题最终成为可能。

如果用户可以控制模式,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的2种类型。注意,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(盖茨比接口(。

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
}
}
`

这需要一些设置,但如果你提前知道你的数据类型,这可能是值得的&需要大量重用碎片。

相关内容

  • 没有找到相关文章

最新更新