0
votes

Im having issues when trying to render blogpost from json file in React

const BlogPost = (props) => {

    const [post, setPost] = useState({
      id: "",
      blogCategory:"",
      blogTitle:"",
      postedOn:"",
      author:"",
      blogImage:"",
      blogText:"",
    });
    const [slug, setSlug] = useState('');


    useEffect(() => {
      const slug = props.match.params.slug;
      const post = blogPost.data.find(post => post.slug == slug);
      setPost(post);
      setSlug(slug)
    }, [post, props.match.params.slug]);

  return(
        <div className="blogPostContainer">
          <Card>
            <span className="blogCategory">{post.blogCategory}</span>
            <h1 className="postTitle">{post.blogTitle}</h1>
            <span>posted on {post.postedOn} by {post.author}</span>
            </div>
          </Card>
        </div>
   )
  }


export default BlogPost
json:

{
    "data" : [
        {
            "id": 1,
            "blogCategory": "Featured",
            "blogTitle" : "Fitness Mantra To Live Fit Life",
            "slug": "fitness-mantra-to-live-fit-life",
            "postedOn": "July 21, 2016",
            "author": "Faiz Khan",
            "blogImage": "fitness-blog-post.jpg",
            "blogText": "Midst first it "
        },
        {
            "id" : 2,
            "blogCategory": "Simple",
            "blogTitle": "Beautiful & Special Moment",
            "slug": "beautiful-and-special-moment",
            "postedOn": "May 03, 2016",
            "author": "Rizwan Khan",
            "blogImage": "beautiful-&-simple.jpg",
            "blogText": "Extremity "
        }
    ]
}

I've added the Json file it pull the information from at the top.

comes up with "TypeError: Cannot read property 'blogCategory' of undefined", even though I've initially made useState as an array pleas help!

2
Where is the blogPost object coming from? I don't see it being a prop.slaid3r

2 Answers

0
votes

This use effect seems to be faulty. It should cause an infinite loop unless the post is always the same value. It probably means that the post is undefined (as the error says) so it must mean that there is no post with the given slug, I would check those values, also might want to change the post.slug == slug to post.slug === slug.

useEffect(() => {
  const slug = props.match.params.slug;
  const post = blogPost.data.find(post => post.slug == slug);
  setPost(post);
  setSlug(slug)
}, [post, props.match.params.slug]);

This state is obsolete inside the given component, it is not used anywhere (assuming this a full code of the component) so it could be removed.

[slug, setSlug] = useState('')

There are two solutions to your issue, considering that props.match.params.slug will eventually hold a valid slug and won't endlessly be undefined/empty/null.

First one is wrapping the setPost with a undefined check like this. Please note I've removed the obsolete setSlug here. I've also removed post from the dependency array as it could lead to infinite loop and is non-required here. I've also added a dependency for blogPost.data in case it has some empty initial data.

useEffect(() => {
  const slug = props.match.params.slug;
  const post = blogPost.data.find(post => post.slug == slug);
  if (post) {
    setPost(post);
  }
}, [blogPost.data, props.match.params.slug]);

The other solution is to add optional chaining for the post object and updating the useEffect like follows. I've also fixed dependency list for the same reason as for the previous approach.

const BlogPost = (props) => {
  const [post, setPost] = useState();

  useEffect(() => {
    const slug = props.match.params.slug;
    const post = blogPost.data.find(post => post.slug == slug);
    setPost(post);
  }, [blogPost.data, props.match.params.slug]);

  return (
    <div className="blogPostContainer">
      <Card>
        <span className="blogCategory">{post?.blogCategory}</span>
        <h1 className="postTitle">{post?.blogTitle}</h1>
        <span>posted on {post?.postedOn} by {post?.author}</span>
      </Card>
    </div >
  )
}
0
votes

There are no issue in your code except extra invalid code tag of </div> inside <Card>

Invalid Code

<div className="blogPostContainer">
          <Card>
            <span className="blogCategory">{post.blogCategory}</span>
            <h1 className="postTitle">{post.blogTitle}</h1>
            <span>posted on {post.postedOn} by {post.author}</span>
            </div>
          </Card>
        </div>

correct code

<div className="blogPostContainer">
          <Card>
            <span className="blogCategory">{post.blogCategory}</span>
            <h1 className="postTitle">{post.blogTitle}</h1>
            <span>posted on {post.postedOn} by {post.author}</span>
          </Card>
        </div>