我正在尝试创建一个简单的
Byline
组件,在我的 MDX 帖子中使用,该组件使用 href="mailto:[email protected]"
和 time
标签显示网站作者,并在其 frontmatter 中给出帖子的日期。
我尝试按照 this Gatsby 教程 学习如何在组件中通过 GraphQL 查询 frontmatter。
我不太了解 React 或 GraphQL,但我知道第一个 (
author
) 是通过 site.siteMetadata.author.name
查询的(我认为?)。
至于第二个,因为它使用了帖子的frontmatter,所以我认为我应该使用
mdx.frontmatter.date
。
我没有让这些发挥作用。我收到这些错误:
无法读取未定义的属性(读取“站点”)
无法读取未定义的属性(读取“mdx”)
我也收到此错误:
There was an error in your GraphQL query:
Variable "$id" is not defined by operation "BylineQuery".
GraphQL request:10:19
9 | }
10 | mdx(id: { eq: $id }) {
| ^
11 | frontmatter {
GraphQL request:2:3
1 |
2 | query BylineQuery {
| ^
3 | site {
这是完整的组件:
import * as React from 'react'
import { graphql } from 'gatsby'
const Byline = ({data }) => {
return (
<div className="byline">
<address>Av <a href="mailto:[email protected]" rel="author">{data.site.siteMetadata.author.name}</a></address>
<time dateTime={data.mdx.frontmatter.computerDate}>{data.mdx.frontmatter.humanDate}</time>
</div>
)
}
export const query = graphql`
query BylineQuery {
site {
siteMetadata {
author {
name
}
}
}
mdx(id: { eq: $id }) {
frontmatter {
computerDate: date(formatString: "YYYY-MM-DD")
humanDate: date(formatString: "D. MMMM YYYY", locale: "nb")
}
}
}
`
export default Byline
gatsby-node.js
:const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.createPages = async ({ graphql, actions, reporter }) => {
const { createPage } = actions
// Define a template for blog post
const blogPost = path.resolve(`./src/templates/blog-post.js`)
// Get all markdown blog posts sorted by date
const result = await graphql(
`
{
allMdx(
sort: { fields: [frontmatter___date], order: ASC }
limit: 1000
) {
nodes {
id
fields {
slug
}
}
}
}
`
)
if (result.errors) {
reporter.panicOnBuild(
`There was an error loading your blog posts`,
result.errors
)
return
}
const posts = result.data.allMdx.nodes
// Create blog posts pages
// But only if there's at least one markdown file found at "content/blog" (defined in gatsby-config.js)
// `context` is available in the template as a prop and as a variable in GraphQL
if (posts.length > 0) {
posts.forEach((post, index) => {
const previousPostId = index === 0 ? null : posts[index - 1].id
const nextPostId = index === posts.length - 1 ? null : posts[index + 1].id
createPage({
path: post.fields.slug,
component: blogPost,
context: {
id: post.id,
previousPostId,
nextPostId,
},
})
})
}
}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `Mdx`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions
createTypes(`
type SiteSiteMetadata {
author: Author
siteUrl: String
social: Social
}
type Author {
name: String
summary: String
}
type Social {
twitter: String
instagram: String
mail: String
}
type MarkdownRemark implements Node {
frontmatter: Frontmatter
fields: Fields
}
type Frontmatter {
title: String
description: String
date: Date @dateformat
}
type Fields {
slug: String
}
`)
}
Byline.js
:(目前只是测试。)
(位于
components
目录中。)
import React from "react"
import { graphql } from "gatsby"
export default function Byline({ data: { mdx } }) {
return (
<div>
<h1>{mdx.frontmatter.title}</h1>
</div>
)
}
export const pageQuery = graphql`
query BylineQuery($id: String) {
mdx(id: { eq: $id }) {
id
body
frontmatter {
title
}
}
}
`
gatsby-config.js
module.exports = {
siteMetadata: {
title: `Magnus Kolstad`,
author: {
name: `Magnus Rengård Kolstad`,
summary: `Summary`,
description: "Artikler skrevet av Magnus Kolstad",
},
description: `Description`,
siteUrl: `https://kolstadmagnus.no/`,
social: {
mail: `[email protected]`,
instagram: `kolstadmagnus`,
twitter: `KolstadMagnus`,
youtube: `UC7QpsGiWwVc9lmnIJvA9OLA`
},
},
plugins: [
`gatsby-plugin-image`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `blog`,
path: `${__dirname}/content/blog`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `pages`,
path: `${__dirname}/src/pages/`,
}
},
{
resolve: `gatsby-plugin-mdx`,
options: {
defaultLayouts: {
default: require.resolve(`./src/components/layout.js`),
},
gatsbyRemarkPlugins: [
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: `900000000000`,
linkImagesToOriginal: false,
backgroundColor: `none`,
},
},
{
resolve: `gatsby-remark-responsive-iframe`,
options: {
wrapperStyle: `margin-bottom: 1.0725rem`,
},
},
`gatsby-remark-prismjs`,
`gatsby-remark-copy-linked-files`,
`gatsby-remark-smartypants`,
],
extensions: [`.md`, `.mdx`],
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `Gatsby Starter Blog`,
short_name: `GatsbyJS`,
start_url: `/`,
background_color: `#ffffff`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`,
},
},
`gatsby-plugin-react-helmet`,
],
}
扩展哈桑的答案:
首先,这里写了一个页面查询。页面查询仅适用于 页。确保您的组件位于页面目录中。
这部分是正确的。页面查询也可以在模板中使用,这意味着它们也是页面,但它们不位于
src/pages
文件夹中,而是位于 src/templates
中(假设指南的项目结构)。
尽管查询看起来应该是这样的:
export const query = graphql`
query BylineQuery($id: String) {
site {
siteMetadata {
author {
name
}
}
}
mdx(id: { eq: $id }) {
frontmatter {
computerDate: date(formatString: "YYYY-MM-DD")
humanDate: date(formatString: "D. MMMM YYYY", locale: "nb")
}
}
}
如果需要,请在 GraphiQL 游乐场 (
localhost:8000/___graphql
) 中使用硬编码 id
检查它,或者将过滤器更改为另一个方便的字段。
事实是,关键部分是您需要使用上下文将
id
从 gatsby-node.js
传递到模板,正如在 tutorial 中推断的那样。例如::
posts.forEach(({ node }, index) => {
createPage({
path: node.fields.slug,
component: path.resolve(`./src/templates/blog-post.js`),
// values in the context object are passed in as variables to page queries
context: {
title: node.title,
id: node.id
},
})
})
title
和id
变量将在blog-post.js
模板中公开(在./src/templates
下),并可用于使用这些值过滤您的帖子(在本例中)。
简化,
gatsby-node.js
创建模板页面(帖子等)并查询每个帖子的特定数据,您需要使用通过上下文发送的提升上下文变量来过滤数据。
首先,这里写了一个页面查询。页面查询仅适用于页面。确保您的组件位于页面目录中。该错误来自您的查询,您使用了动态参数“$id”,但没有传递变量。
export const query = graphql`
query BylineQuery($id: String) {
site {
siteMetadata {
author {
name
}
}
}
mdx(id: { eq: $id }) {
frontmatter {
computerDate: date(formatString: "YYYY-MM-DD")
humanDate: date(formatString: "D. MMMM YYYY", locale: "nb")
}
}
}
`
你的查询应该是这样的。检查文档(https://www.gatsbyjs.com/docs/how-to/querying-data/page-query/)