How to make a Gatsby Storyblok blog index page

173 views Asked by At

I'm trying to render a blog page to show all the Storyblok blog entries:

Here's my blog.js page

import React from "react"
import Layout from "../components/layout"
import Blogposts from "../components/BlogPosts"
import StoryblokService from '../utils/storyblok-service'

export default class extends React.Component {
  state = {
    stories: {
    }
  }
  async getInitialStories() {
    let { data: { stories } } = await StoryblokService.get('cdn/stories?starts_with=blog')
    return stories
  }
  async componentDidMount() {
    let stories = await this.getInitialStories()
    if(stories.content) this.setState({ stories })
    console.log(stories)
    setTimeout(() => StoryblokService.initEditor(this), 200)
  }
  render() {
    return (
      <Layout>
        <Blogposts stories={this.state.stories.content} />
      </Layout>
    )
  }
}

console.log(stories)

returns my blog posts enter image description here

Blogposts component looks like this

import React from 'react'
const BlogPosts = (stories) => (
    <ul>
      {stories.map((story) => (
          <li key={story._uid}>
            { story.title }
          </li>
        )
      )}
    </ul>
)
export default BlogPosts 

But when I run it I get this error.

TypeError: undefined is not a function (near '...stories.map...') BlogPosts src/components/BlogPosts.js:5

2 | 
  3 | const BlogPosts = (stories) => (
  4 |
> 5 |     <ul>
  6 |       {stories.map((story) => (
  7 |           <li key={story._uid}>
  8 |             { story.title }

Any help would be hugely appreciated! Thanks.

2

There are 2 answers

6
Artem Matiushenko On BEST ANSWER

You are passing undefined to Blogposts because content does not exist in your state at the beginning, and you set it only after your data has been fetched.

1
Nobal Mohan On

You are passing stories here <Blogposts stories={this.state.stories.content} /> but the value is fetched via async. So the template is trying to render before the value is available in const BlogPosts = (stories) => ()

Change <Blogposts stories={this.state.stories.content} /> to {this.state.stories.content && <Blogposts stories={this.state.stories.content} />}