如何解决Gatsby 使用 slug 查询特定帖子
我正在尝试使用 slug 查询特定博客文章 - 以便根据 slug 显示特定帖子。
我遇到了以下错误:TypeError: Cannot read property 'Title' of null
这是下面代码的逻辑:
- 在我的过滤器中指定 slug
- 然后
eq
(等于)变量$slug
- 上面的变量将允许我动态过滤,而不是手动为后端的每个帖子进行查询
- 然后我用
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
注意 S
中的大写 SinglePost
。
也就是说,将 $slug
传递给模板/页面组件的唯一方法是使用上下文 API,这基本上就是您在 gatsby-node.js
中所做的。在那里,您应该查询所有帖子并使用 createPages API,同时遍历它们以创建动态页面。在那里,您将公开每个帖子的上下文,并且您可以告诉 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,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,},})
})
}
注意:当然,为您的理智调整降价方法 (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 游乐场来测试您的查询,以便了解字段的命名方式或嵌套结构的外观,这将使您无需了解title
字段是如何命名的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。