Gatsby 使用 slug 查询特定 post

Gatsby Query for specific post using slug

我正在尝试使用 slug 查询特定博客 post - 以便根据 slugpost 显示特定的 post =34=].

我遇到了以下错误:TypeError: Cannot read property 'Title' of null

这是以下代码的逻辑:

  1. 在我的过滤器中指定 slug
  2. 然后eq(等于)变量$slug
  3. 以上变量将允许我动态过滤,而不是手动查询后端中的每个 post
  4. 然后我在前端用data.sanityPosts.Title
  5. 查询数据
  6. 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 字段的命名方式。