【问题标题】:Displaying all blog posts with Gatsby Contentful使用 Gatsby Contentful 显示所有博客文章
【发布时间】:2025-12-25 04:25:12
【问题描述】:

我试图在 Gatsby 的索引页面上显示我所有的内容博客文章,但我收到了一个错误。

我在gatsby-node.js 上创建帖子页面,如下所示:

const path = require(`path`)
// Log out information after a build is done
exports.onPostBuild = ({ reporter }) => {
  reporter.info(`Your Gatsby site has been built!`)
}
// Create blog pages dynamically
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const blogPostTemplate = path.resolve(`src/templates/blogPost.js`)
  const result = await graphql(`
    query {
      allContentfulPost {
        edges {
          node {
            postTitle
            slug
          }
        }
      }
    }
  `)
  result.data.allContentfulPost.edges.forEach(edge => {
    createPage({
      path: `${edge.node.slug}`,
      component: blogPostTemplate,
      context: {
        title: edge.node.postTitle,
        slug: edge.node.slug,
      },
    })
  })
}

基于此模板:

import React from "react"
import { graphql } from "gatsby"
import styled from "styled-components"

export const pageQuery = graphql`
  query($slug: String!) {
    post: contentfulPost(slug: { eq: $slug }) {
      slug
      postTitle
      postContent {
        childMarkdownRemark {
          html
        }
      }
      postImage {
        title
        fluid {
          src
        }
      }
    }
  }
`

function blogPost({ data }) {
  return (
    <div>
      <img
        src={data.post.postImage.fluid.src}
        alt={data.post.postImage.title}
      ></img>
      <h1>{data.post.postTitle}</h1>
      <h3
        dangerouslySetInnerHTML={{
          __html: data.post.postContent.childMarkdownRemark.html,
        }}
      />
    </div>
  )
}

export default blogPost

现在我尝试创建一个包含所有博客文章的组件,以便我可以在我的index.js 页面上显示它,如下所示:

import { Link, graphql, StaticQuery } from "gatsby"
import React from "react"
import styled from "styled-components"

function BlogSection() {
  return (
    <StaticQuery
      query={graphql`
        query blogQuery {
          
          allContentfulPost {
            edges {
              node {
                slug
                postTitle
                postImage {
                  file {
                    url
                    fileName
                  }
                }
                postContent {
                  postContent
                }
                postDate
              }
            }
          }
        }
      `}
      render={data => (
        <ul>
          <Link to={data.allContentfulPost.edges.node.slug}> //here's where the error happens
            {data.allContentfulPost.edges.node.postTitle}
          </Link>
        </ul>
      )}
    />
  )
}

export default BlogSection

但我收到一个错误 Cannot read property 'slug' of undefined,这让我疯狂了好几天。

任何帮助将不胜感激!

【问题讨论】:

  • 边是一个数组
  • @xadm 那我该怎么办?

标签: reactjs graphql gatsby contentful


【解决方案1】:

用途:

<ul>
  {data.allContentfulPost.edges.map(({ node }) => {
    return <Link to={node.slug} key={node.slug}>
    {node.postTitle}
  </Link>
  })}
</ul>

您正在查询来自 Contentful (allContentfulPost) 的所有罐子,这些罐子遵循嵌套结构,内部有一个 edges 和一个 node:最后一个包含您帖子的所有信息(因为嵌套结构,你有slugpostTitle 等)所以node 确实是你的帖子。也就是说,您只需要遍历edges,这是您的帖子数组。在之前的sn-p中:

data.allContentfulPost.edges.map(({ node })

在循环遍历它的同时,您正在解构可迭代变量 ({ node })。您可以将其别名为更简洁的方法,例如:

<ul>
  {data.allContentfulPost.edges.map(({ node: post }) => {
    return <Link to={post.slug} key={post.slug}>
    {post.postTitle}
  </Link>
  })}
</ul>

在所有循环中使用key attribute 很重要,因为它有助于 React 了解哪些元素正在发生变化。

【讨论】:

  • 感谢您无数次!不知何故,我知道这方面的逻辑,但我是新手,我的语法总是错误的。这在我第一次刷新时起作用。知道如何限制要显示的帖子数量吗?
  • 谢谢:)。为了限制帖子,你有一个 GraphQL 过滤器(limit 一个)应该可以解决问题。使用 localhost:8000/___graphql 游乐场测试您的查询和过滤器
  • 非常感谢!有用。请再问一个问题:)我怎样才能使蛞蝓动态?例如,当我从另一个页面单击帖子时,它会返回 404。例如,我在主页和博客页面中显示帖子。当我从主页点击帖子时,slug 是domain.com/post,但是当我从博客页面点击它时,它的domain.com/blog/post 并返回 404。这是我从模板页面查询:query($slug: String!) { post: contentfulPost(slug: { eq: $slug })
  • 请打开一个新的答案。很难以这种方式查看代码。查看 Gatsby 的教程,这个配置在gatsby-node.js