1

Question regarding fetching nested data in react.

APIs

  1. https://jsonplaceholder.typicode.com/posts
  2. https://jsonplaceholder.typicode.com/posts/${postId}/comments

Able to fetch list of posts. now want to fetch list of comments from when click on post

here is code so far

import React, { useEffect, useState } from "react";
import Post from "./Post";

const [posts, setPosts] = useState([]);
const [comments, setComments] = useState([]);

function App() {
  const [posts, setPosts] = useState([]);
  const [comments, setComments] = useState([]);

useEffect(() => {
  const loadposts = async() => {
    const resp = await fetch("https://jsonplaceholder.typicode.com/posts?userId=1");
    const data = await resp.json();
    setPosts(data);
  }
  loadposts();
}, []);

return (
  <div className="App">
    <ul>
      {posts.map((post) => 
      (
        <div>
          <li key={post.id}>
            <Post 
            userId={post.id}
            title={post.title} 
            body={post.body} 
            />
          </li>
      </div>
      ))
      }
    </ul>
  </div>
);
}

export default App;

function Post({title, body, postId}) {
  
  return (
      <div>
          <h5>{postId}</h5>
          <h1>{title}</h1>
          <p>{body}</p>
      </div>
  )
}

export default Post

appreciate any help. thanks

5
  • So you've the API endpoint for fetching comments by post id and a child Post component and postId prop. Have you tried making the request to the endpoint with the specific data? When do you want, or need, to fetch the comments for each post? Commented May 31, 2021 at 22:54
  • @Drew Reese .. Thanks for getting back. I did add request to fetch comments with given {post id} when click on post title but it did not return anything Commented May 31, 2021 at 22:59
  • SHow us what you tried. There isn't any onClick code shown here Commented May 31, 2021 at 23:02
  • What and where are you clicking something? Commented May 31, 2021 at 23:03
  • @DrewReese I would like to display selected post fetch data from comments when I click on post. I added handleclick on title function in case currentpostId === post.id. but it did not do anything Commented Jun 1, 2021 at 1:23

2 Answers 2

2

Firstly, the "/posts" endpoint returns posts by users, so the query "/posts?userId=1" will return all the posts by user id 1. You mistakenly passed a userId prop to the Post component instead of the specific post's id, i.e.

<Post userId={post.id} title={post.title}  body={post.body} />

The React key should also be placed on the outer-most element being mapped, the div in your case, but since li is already a block level element the div is basically extraneous.

<ul>
  {posts.map((post) => (
    <li key={post.id}> // <-- remove div and place React key on li
      <Post
        postId={post.id} // <-- pass the post's id
        title={post.title}
        body={post.body}
      />
    </li>
  ))}
</ul>

In Post component create a fetch comments utility and click handler, and attach the click handler to the title header. Conditionally render the comments. If it wasn't already clear, you'll move the comments state into Posts so each post component maintains its own copy. The following is an example for rendering out the comments once fetched, you can use whatever conditional rendering and field subset of your choosing.

const fetchComments = async (postId) => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/posts/${postId}/comments`
  );
  return response.json();
};

function Post({ title, body, postId }) {
  const [comments, setComments] = useState([]);

  const clickHandler = () => {
    fetchComments(postId).then(setComments);
  };

  return (
    <div>
      <h5>{postId}</h5>
      <h1 onClick={clickHandler}>{title}</h1>
      <p>{body}</p>
      {comments.length && (
        <>
          Comments:
          <ul>
            {comments.map(({ id, email, name, body }) => (
              <li key={id}>
                <dl>
                  <dt>{email} - {name}</dt>
                  <dd>{body}</dd>
                </dl>
              </li>
            ))}
          </ul>
        </>
      )}
    </div>
  );
}

Edit how-to-fetch-nested-data-in-react

Sign up to request clarification or add additional context in comments.

Comments

0

Working solution if anyone looking for


function Post() {
const {id} = useParams();
const [comments, setComments] = useState([]);

useEffect(() => {
    fetch(`https://jsonplaceholder.typicode.com/posts/${id}/comments`)
    .then((res) => res.json())
    .then(setComments)
    .catch((error) => {
        console.log(error)
    })
    console.log("setComments: ", setComments)
}, [])

    return (
        <div>
            {comments && comments.map((comment) => (
                <div key={comment.id}>
                    <p>{comment.body}</p>
                </div>

            ))}

        </div>
    )
}
export default Post

then update rendering 

    <div className="App">
      <Switch>
     <Route exact path='/'>
        {posts.map((post) => (
         <article key={post.id}> 
          <h1>{post.title}</h1>
            <Link to ={`/${post.id}`}>
              <p>{post.body}</p>
            </Link>
       </article>
      ))}
   </Route>

     <Route path ='/:id'>
        <Post/>
     </Route>
   </Switch>

  </div>

   

    
  

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.