Cas*_*mir 7 dry contentful graphql gatsby
我有一个Gatsby项目,它有两个不同类型的内容非常相似的GraphQL查询:常规页面和维基文章.
页面由slug
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
}
}
}
`
Run Code Online (Sandbox Code Playgroud)
由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
+ }
}
}
`
Run Code Online (Sandbox Code Playgroud)
除了维基文章的附加部分和子部分,查询是相同的.为了保持DRY,我怎样才能将页面字段移动到一个单独的片段中,尽管它的类型不同,也可以传播到wiki文章查询中?GraphQL可以提供如下内容:
fragment pageFields on [ContenfulPage, ContenfulWikiArticle] {
...
}
Run Code Online (Sandbox Code Playgroud)
Gatsby 最近发布的版本允许用户为 graphql 模式设置自己的类型,使这个问题最终成为可能。
如果用户可以控制架构,graphql 总是可能的,但是由于最近的 Gatsby 更新,用户最终可以自己实现这一点。
为了建立一个简单的例子,我将gatsby-transformer-json在一个像这样的简单文件夹上使用
jsonFolder
|--one.json { "type": "One", "name": "a", "food": "pizza" }
`--two.json { "type": "Two", "name": "b", "game": "chess" }
Run Code Online (Sandbox Code Playgroud)
并使用选项声明我的类型名称:
{
resolve: `gatsby-transformer-json`,
options: {
typeName: ({ object }) => object.type,
},
},
Run Code Online (Sandbox Code Playgroud)
现在我有两种类型是为我创建的。我可以在其中一个上创建一个片段,但不能同时创建:
export const name = graphql`
fragment name on One {
name
}
`
export const pageQuery = graphql`
query {
one {
...name
}
two {
...name <-- ?? throw type error
}
}
`
Run Code Online (Sandbox Code Playgroud)
让我们解决这个问题。
我将使用一个新的 APIcreateTypes来为每个 json 注册一个新接口和 2 种类型。需要注意的是JsonNode同时包含常见的领域One和Two:
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)
}
Run Code Online (Sandbox Code Playgroud)
神奇发生在这一行,其中One&Two实现了JsonNode(自定义接口)和Node(Gatsby 的接口)。
type One implements Node & JsonNode { ... }
Run Code Online (Sandbox Code Playgroud)
现在我可以编写一个实现的片段,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
}
}
`
Run Code Online (Sandbox Code Playgroud)
这需要一些设置,但如果您提前知道您的数据类型并且需要大量重用片段,那么这可能是值得的。
| 归档时间: |
|
| 查看次数: |
1030 次 |
| 最近记录: |