Arĝenta kato
Arĝenta kato

Reputation: 23

Cannot read property 'slug' of undefined, but absolutely exist

I am trying to make a blog by using Gatsby.

I wanted to use Asciidoc instead of Markdown, so I wrote the following code concerning the official code.

const blogArticleTemplate = path.resolve(
  "./src/components/templates/article/index.tsx"
)
const articles = result.data.allAsciidoc.edges

if (0 < articles.length) {
  articles.forEach(( node, index ) => {
    const slug = node.pageAttributes.slug
    const previousArticle = index === 0 ? null : articles[index - 1].node.pageAttributes.slug
    const nextArticle = index === articles.length - 1 ? null : articles[index + 1].node.pageAttributes.slug

    createPage({
      slug,
      component: blogArticleTemplate,

      context: {
        slug: slug,
        previousArticle,
        nextArticle,
      },
    })
  })
}

but, this code isn't working. Returns the following error.

error "gatsby-node.js" threw an error while running the createPages lifecycle:

Cannot read property 'slug' of undefined

  33 |     articles.forEach(( node, index ) => {
> 34 |       const slug = node.pageAttributes.slug
     |                                        ^
  35 |       const previousArticle = index === 0 ? null : articles[index - 1].node.pageAttributes.slug
  36 |       const nextArticle = index === articles.length - 1 ? null : articles[index + 1].node.pageAttributes.slug
  37 | 

The error message says that pageAttributes is undefined, but I have confirmed that pageAttributes isn't undefined.

Insert console.log (node) into my code, you can see that pageAttributes exists, as you can see.

[Object: null prototype] {
  node: [Object: null prototype] {
    pageAttributes: [Object: null prototype] { slug: '/test' }
  }
}

So, I have two questions:

Thanks.

Upvotes: 1

Views: 1596

Answers (1)

Ferran Buireu
Ferran Buireu

Reputation: 29316

You are accessing wrong the nested iterable object. You have defined articles but when iterating through them, node is not the nested object, is just the article itself, the iterable object. You need to downside one level.

Change the loop to:

articles.forEach(({ node } ) => {
   const slug = node.pageAttributes.slug
   // rest of the code
}

With the snippet above, you are destructuring the iterable object (article) to get the node itself. Alternatively, if you want to keep your previous structure, just access to:

articles.forEach(( node, index ) => {
    const slug = node.node.pageAttributes.slug
    // rest of the code
}

In that case, I would suggest a change of naming to:

articles.forEach(( article, index ) => {
    const slug = article.node.pageAttributes.slug
    // rest of the code
}

Upvotes: 1

Related Questions