Ilir
Ilir

Reputation: 656

Displaying all blog posts with Gatsby Contentful

Im trying to display all my Contentful blog posts to my index page in Gatsby but i get an error.

im creating the Posts pages on gatsby-node.js like this:

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,
      },
    })
  })
}

based on this template:

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

Now i try to create a component which will hold all the blog posts so i can display it on my index.js page, like this:

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

But i get an error Cannot read property 'slug' of undefined which is driving me crazy for days.

any help would be appreciated!

Upvotes: 1

Views: 451

Answers (1)

Ferran Buireu
Ferran Buireu

Reputation: 29320

Use:

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

You are querying all pots from Contentful (allContentfulPost) which following the nested structure, has an edges and a node inside: this last one has all the information of your posts (because of the nested structure, you have the slug, the postTitle, etc) so the node, is indeed your post. That said, you only need to loop through edges, which is an array of your posts. In the previous snippet:

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

You are destructuring the iterable variable at the same time you loop through it ({ node }). You can alias it for a more succint approach like:

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

It's important to use the key attribute in all loops since it will help React to know what elements are changing.

Upvotes: 2

Related Questions