biscuit
biscuit

Reputation: 29

How to fetch from backend database to display on frontend using react?

I'm trying to fetch from my backend database (MongoDB) on my localhost to display all blogposts.

I'm assuming I need to iterate through each blogpost on the frontend. Right now, only "Author" and "Comments" display, but with no actual data.

What would that syntax look like?

Here's what the React page looks like where I'm fetching and displaying.

import React, { Component } from 'react'

class Blog extends Component {
    constructor() {
        super()
    
        this.state = {
          blogPost: [],
          finishedLoading: true
        }
      }    
    
    async componentDidMount() {    
        const response = await fetch('http://localhost:8000/api/blogPosts/all')
        const json = await response.json()
        this.setState({ blogPost: json.blogPosts, finishedLoading: false })
      }
    
    reload = async () => {
        const response = await fetch('http://localhost:8000/api/blogPosts/all')
        const json = await response.json()
        this.setState({ blogPost: json.blogPosts, finishedLoading: true })
      }
    
    render() {
        
    if (this.state.blogPost.length === 0) {
        return (
          <div className="App">
            <h1>No blogposts have been posted!</h1>
          </div>
        )
    }
   

    return (
            <div class="blogPost">
                <h2>{this.state.blogPost.title}</h2>
                <p> Author: {this.state.blogPost.author}</p>
                <p>{this.state.blogPost.content}</p>
                <p>Comments:</p>

                <ul>
                
                </ul>
            </div>
        )
    }
}

export default Blog

Upvotes: 0

Views: 2198

Answers (2)

aryanm
aryanm

Reputation: 1259

You are setting this.state.blogPost to an array of blogPosts that you receive from your database. So, this.state.blogPost.author will be undefined since an array won't have a .author property. The items inside the array will have the property instead, accessed like so: this.state.blogPost[0].author to get the author of the first post.

To display a div for every item in the array, you need to loop through the array in your render function with .map:

return (
        this.state.blogPost.map((post, index) => (
            <div class="blogPost" key={index}>
                <h2>{post.title}</h2>
                <p> Author: {post.author}</p>
                <p>{post.content}</p>
                <p>Comments:</p>
                
                <ul>
                
                </ul>
            </div>
        ));
        
    )

Edit: looks like I was beat to the punch!

Upvotes: 0

Praveen Kumar Purushothaman
Praveen Kumar Purushothaman

Reputation: 167240

You're supposed to iterate through the contents but you're doing only once, that too on an array:

return (
  <div class="blogPost">
    <h2>{this.state.blogPost.title}</h2>
    <p> Author: {this.state.blogPost.author}</p>
    <p>{this.state.blogPost.content}</p>
    <p>Comments:</p>

    <ul></ul>
  </div>
);

The above code is wrong. What you need to do is iterate the contents of this.state.blogPost, which is an array of blog objects:

return this.state.blogPost.map((blog, key) => (
  <div class="blogPost" key={key}>
    <h2>{blog.title}</h2>
    <p> Author: {blog.author}</p>
    <p>{blog.content}</p>
    <p>Comments:</p>
    <ul></ul>
  </div>
));

You might need to do the same thing to fetch the comments too. Say, the comments are an array of comments in the object, then do this:

return this.state.blogPost.map((blog, key) => (
  <div class="blogPost" key={key}>
    <h2>{blog.title}</h2>
    <p> Author: {blog.author}</p>
    <p>{blog.content}</p>
    <p>Comments:</p>
    <ul>
      {blog.comments.length > 0 ? (
        blog.comments.map((c, k) => <li key={key}>{c}</li>)
      ) : (
        <li>No comments.</li>
      )}
    </ul>
  </div>
));

Full code here:

import React, { Component } from "react";

class Blog extends Component {
  constructor() {
    super();

    this.state = {
      blogPost: [],
      finishedLoading: true
    };
  }

  async componentDidMount() {
    const response = await fetch("http://localhost:8000/api/blogPosts/all");
    const json = await response.json();
    this.setState({ blogPost: json.blogPosts, finishedLoading: false });
  }

  reload = async () => {
    const response = await fetch("http://localhost:8000/api/blogPosts/all");
    const json = await response.json();
    this.setState({ blogPost: json.blogPosts, finishedLoading: true });
  };

  render() {
    if (this.state.blogPost.length === 0) {
      return (
        <div className="App">
          <h1>No blogposts have been posted!</h1>
        </div>
      );
    }

    return this.state.blogPost.map((blog, key) => (
      <div class="blogPost" key={key}>
        <h2>{blog.title}</h2>
        <p> Author: {blog.author}</p>
        <p>{blog.content}</p>
        <p>Comments:</p>
        <ul>
          {blog.comments.length > 0 ? (
            blog.comments.map((c, k) => <li key={key}>{c}</li>)
          ) : (
            <li>No comments.</li>
          )}
        </ul>
      </div>
    ));
  }
}

export default Blog;

Upvotes: 1

Related Questions