Reputation: 656
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
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