Gatsby 使用 slug 查询特定 post
Gatsby Query for specific post using slug
我正在尝试使用 slug 查询特定博客 post - 以便根据 slugpost 显示特定的 post =34=].
我遇到了以下错误:TypeError: Cannot read property 'Title' of null
这是以下代码的逻辑:
- 在我的过滤器中指定 slug
- 然后
eq
(等于)变量$slug
- 以上变量将允许我动态过滤,而不是手动查询后端中的每个 post
- 然后我在前端用
data.sanityPosts.Title
查询数据
Title
由于某种原因未定义
export const query = graphql` {
sanityPosts(slug: {current: {eq: "$slug"}}) {
Title
}
}
`;
const singlePost = ({ data }) => (
<Layout>
<Header />
<div>
<h1>{data.sanityPosts.Title}</h1>
</div>
<Footer />
</Layout>
)
export default singlePost
为什么 Title
未定义?我怎样才能更好地解决这个问题?
您的组件应该如下所示:
export const query = graphql` {
sanityPosts(slug: {current: {eq: "$slug"}}) {
Title
}
}
`;
const SinglePost = ({ data }) => (
<Layout>
<Header />
<div>
<h1>{data.sanityPosts.Title}</h1>
</div>
<Footer />
</Layout>
)
export default SinglePost
注意 SinglePost
中大写的 S
。
说,将 $slug
传递给 template/page 组件的唯一方法是使用上下文 API,这基本上就是您在 gatsby-node.js
中所做的.在那里,您应该查询所有 post 并使用 createPages API 循环访问它们以创建动态页面。在那里,您将公开每个 post 的上下文,并且您可以告诉 Gatsby 此模板所在的位置以便传递数据。
答案缺少信息,但解决方法应该如下所示:
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const slug = createFilePath({ node, getNode, basePath: `pages` })
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: path.resolve(`./src/templates/blog-post.js`),
context: {
// Data passed to context is available
// in page queries as GraphQL variables.
slug: node.fields.slug,
},
})
})
}
注意:当然,为您的 Sanity one 调整降价方法 (allMarkdownRemark
)
现在您可以访问模板中的 slug
:
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
export default function BlogPost({ data }) {
const post = data.markdownRemark
return (
<Layout>
<div>
<h1>{post.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</div>
</Layout>
)
}
export const query = graphql`
query($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
title
}
}
}
`
注意:再次为您的 Sanity 更换降价方法
您可以按照 Gatsby 文档中的完整指南进行操作:https://www.gatsbyjs.com/docs/tutorial/part-seven/
另请记住,您已经在 localhost:8000/___graphql
公开了 GraphQL playground 来测试您的查询,以便了解字段的命名方式或嵌套结构的外观,这将节省您的时间了解 title
字段的命名方式。
我正在尝试使用 slug 查询特定博客 post - 以便根据 slugpost 显示特定的 post =34=].
我遇到了以下错误:TypeError: Cannot read property 'Title' of null
这是以下代码的逻辑:
- 在我的过滤器中指定 slug
- 然后
eq
(等于)变量$slug
- 以上变量将允许我动态过滤,而不是手动查询后端中的每个 post
- 然后我在前端用
data.sanityPosts.Title
查询数据
Title
由于某种原因未定义
export const query = graphql` {
sanityPosts(slug: {current: {eq: "$slug"}}) {
Title
}
}
`;
const singlePost = ({ data }) => (
<Layout>
<Header />
<div>
<h1>{data.sanityPosts.Title}</h1>
</div>
<Footer />
</Layout>
)
export default singlePost
为什么 Title
未定义?我怎样才能更好地解决这个问题?
您的组件应该如下所示:
export const query = graphql` {
sanityPosts(slug: {current: {eq: "$slug"}}) {
Title
}
}
`;
const SinglePost = ({ data }) => (
<Layout>
<Header />
<div>
<h1>{data.sanityPosts.Title}</h1>
</div>
<Footer />
</Layout>
)
export default SinglePost
注意 SinglePost
中大写的 S
。
说,将 $slug
传递给 template/page 组件的唯一方法是使用上下文 API,这基本上就是您在 gatsby-node.js
中所做的.在那里,您应该查询所有 post 并使用 createPages API 循环访问它们以创建动态页面。在那里,您将公开每个 post 的上下文,并且您可以告诉 Gatsby 此模板所在的位置以便传递数据。
答案缺少信息,但解决方法应该如下所示:
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const slug = createFilePath({ node, getNode, basePath: `pages` })
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: path.resolve(`./src/templates/blog-post.js`),
context: {
// Data passed to context is available
// in page queries as GraphQL variables.
slug: node.fields.slug,
},
})
})
}
注意:当然,为您的 Sanity one 调整降价方法 (allMarkdownRemark
)
现在您可以访问模板中的 slug
:
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
export default function BlogPost({ data }) {
const post = data.markdownRemark
return (
<Layout>
<div>
<h1>{post.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</div>
</Layout>
)
}
export const query = graphql`
query($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
title
}
}
}
`
注意:再次为您的 Sanity 更换降价方法
您可以按照 Gatsby 文档中的完整指南进行操作:https://www.gatsbyjs.com/docs/tutorial/part-seven/
另请记住,您已经在 localhost:8000/___graphql
公开了 GraphQL playground 来测试您的查询,以便了解字段的命名方式或嵌套结构的外观,这将节省您的时间了解 title
字段的命名方式。