Reauburt
Reauburt

Reputation: 21

Cannot read property 'allContentfulBlogPost' of undefined" after moving query from index.js to component in GatsbyJS (with Contenful and GraphQL)

Moving a query from index.js to midsection.js (a component) gives Cannot read property of undefined.

I made a website with GatsbyJS which gets it's content from Contentful. I accomplished this by following the Build a blazing fast website with GatsbyJS and Contentful tutorial: https://www.youtube.com/watch?v=wlIdop5Yv_Y

In the tutorial you learn the basics of making a query which shows your content from Contentful on the homepage.

Because I like to use Bulma and I'm pretty new to GatsbyJS (new to React as well) I decided to download the Gatsby-Bulma-Quickstart (https://www.gatsbyjs.org/starters/amandeepmittal/gatsby-bulma-quickstart) and compare it to my own website and use what I need.

I decided to use the component structure used in the Quickstart and wanted to move the query for getting my content from the index.js to the midsection.js.

I got everything working until I moved the query.

My index.js looked like this:

import React from 'react'
import { Link } from 'gatsby'
// import Layout from '../components/layout';

const BlogPost = ({node}) => {
  return (
    <li>
      <Link to={node.slug}><h3>{node.title}</h3></Link>
      <img src={node.heroImage.resize.src} />
      <div>{node.description.childMarkdownRemark.excerpt}</div>
    </li>
  )
}

const IndexPage = ({data}) => (
  <ul className='blog-post'>
    {data.allContentfulBlogPost.edges.map((edge) => <BlogPost node={edge.node} />)}
  </ul>
)

// const IndexPage = () => <Layout />;

export default IndexPage

export const pageQuery = graphql`
  query pageQuery {
    allContentfulBlogPost (filter: {
      node_locale: {eq: "en-US"}
    },
    sort:{ fields: [publishDate], order: DESC }
    ) {
      edges {
        node {
          title
          slug
          description {
            childMarkdownRemark {
              excerpt
            }
          }
          heroImage {
            resize(width: 300, height: 300) {
              src
            }
          }
        }
      }
    }
  }
`

Note: This works, this shows my content. (But as you can see the components etc from the Quickstart are not included (yet))

This is what my index.js looks like right now:

import React from 'react'

import Layout from '../components/layout';


const IndexPage = () => <Layout />;

export default IndexPage

And this is what my midsection.js looks like right now:

import React from 'react'
import { Link } from 'gatsby'

import './style.scss'

const BlogPost = ({node}) => {
  return (
    <li>
      <Link to={node.slug}><h3>{node.title}</h3></Link>
      <img src={node.heroImage.resize.src} />
      <div>{node.description.childMarkdownRemark.excerpt}</div>
    </li>
  )
}

const Midsection = ({data}) => (
  <ul className="blog-post">
    {data.allContentfulBlogPost.edges.map((edge) => <BlogPost node={edge.node} />)}
  </ul>
)

export default Midsection

export const pageQuery = graphql`
  query pageQuery {
    allContentfulBlogPost (filter: {
      node_locale: {eq: "en-US"}
    },
    sort:{ fields: [publishDate], order: DESC }
    ) {
      edges {
        node {
          title
          slug
          description {
            childMarkdownRemark {
              excerpt
            }
          }
          heroImage {
            resize(width: 300, height: 300) {
              src
            }
          }
        }
      }
    }
  }
`

Using this way of moving the query to a component gives this error in the browser: TypeError: Cannot read property 'allContentfulBlogPost' of undefined

I'd expected to use the midsection.js component for columns to show available "blog posts" from Contentful. Instead this only works straight from index.js.

Is there some way the query is not working because I moved it from the root folder to the components folder? And if so, what do I need to do to get the result I want?

Upvotes: 1

Views: 1299

Answers (1)

Reauburt
Reauburt

Reputation: 21

With an colleague helping me, we found an solution by following these steps:

Change layout.js to:

import './style.scss'

const Layout = ({ children }) => children

export default Layout

Change index.js to:

import React from 'react'
import Layout from '../components/layout';
import Helmet from '../components/helmet';
import Header from '../components/header';
import Midsection from '../components/midsection';
import Footer from '../components/footer';

const IndexPage = ({data}) => (
  <Layout>
    <Helmet />
    <Header />
    <Midsection posts={data.allContentfulBlogPost.edges}/>
    <Footer />
  </Layout>
)

export default IndexPage

export const pageQuery = graphql`
  query pageQuery {
    allContentfulBlogPost (filter: {
      node_locale: {eq: "en-US"}
    },
    sort:{ fields: [publishDate], order: DESC }
    ) {
      edges {
        node {
          title
          slug
          description {
            childMarkdownRemark {
              excerpt
            }
          }
          heroImage {
            resize(width: 300, height: 300) {
              src
            }
          }
        }
      }
    }
  }
`

Change midsection.js to:

import React from 'react'
import Link from 'gatsby-link'
import './style.scss'

const BlogPost = ({node}) => {
  return (
    <li>
      <Link to={node.slug}><h3>{node.title}</h3></Link>
      <img src={node.heroImage.resize.src} />
      <div>{node.description.childMarkdownRemark.excerpt}</div>
    </li>
  )
}

const Midsection = ({ posts }) => (
  <ul className="blog-post">
    {posts.map(post => (
      <BlogPost key={post.node.slug} node={post.node} />
    ))}
  </ul>
)

export default Midsection

So what was the problem and what solved it?

The query used in this situation is a pageQuery which means that it only works from pages found in the pages folder. If you want to use the data in a component you have to pass it through :)

Upvotes: 1

Related Questions