0

App.js:

import React, { Fragment } from "react";
import Header from "./components/Header";
import PostList from "./components/PostList";
import Post from "./components/Post";
import TagList from "./components/TagList";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

const App = () => {
  return (
    <Fragment>
      <Router>
        <Header />

        <Switch>
          <Route exact path="/" component={PostList} />
          <Route path="/tags" component={TagList} />
          <Route path="/posts/:id" component={Post} />
        </Switch>
      </Router>
    </Fragment>
  );
};

export default App;

Post.js:

import React, { useEffect, useState } from "react";
import Tag from "./Tag";
import { useParams } from "react-router-dom";
import axios from "axios";

const Post = () => {
  const { id } = useParams();
  const [post, setPost] = useState({});

  useEffect(() => {
    const fetchPost = async () => {
      try {
        const res = await axios.get(`/api/posts/${id}`);

        setPost(res.data);
      } catch (err) {
        console.error(err);
      }
    };
    fetchPost();
  }, []);

  return (
    <div>
      <h2>{post.title}</h2>
      <p>{post.text}</p>
      <div>
        {post.tags.map((tag) => (
          <Tag key={tag._id} tag={tag} />
        ))}
      </div>
    </div>
  );
};

export default Post;

I'm trying to get the skeleton for a simple blog site up and running but I'm having issues with the Post component. When navigating to a specific post with the route '/posts/:id' the useEffect that's supposed to grab the post from my API doesn't seem to run, and inevitably I end up with a 'post.tags is undefined' error. Everything else is working correctly - API responds as expected to requests from Postman and 'useParams' is grabbing the post id from the URL just fine - it's just that the useEffect isn't running at all (console.logs aren't showing up either).

I've had no issues doing things this way in previous projects - in fact the useEffect in the TagList component is virtually identical and the /tags route works as expected, so I'm not sure what I'm missing?

4
  • did you try to put a console.log at the beginning of the useEffect to see if you get in or if it's just the response of the fetch that is empty ? Commented Dec 11, 2020 at 14:18
  • post.tags.map will throw an error first time your component renders because there is no such property/method on the default object you pass to useState. Do you see the axios request in the network inspector? If so what response from your API? Other than the obvious problem I pointed out at the beginning, this isn't really something we can help with for no more than you've provided. Commented Dec 11, 2020 at 14:19
  • first try putting in a console.log inside the useEffect but at the top to see if you are actually entering inside it or not. Commented Dec 11, 2020 at 14:24
  • No API requests turn up in my console and neither do my console.logs regardless of where I place them in the useEffect. The API responds fine to identical requests made from Postman or from the browser Commented Dec 11, 2020 at 14:44

1 Answer 1

1

useEffect runs only at first render, and then at any other render IF the dependencies specified have changed. Since you added there an empty array, those never change.

If you want useEffect to run again when the post id has changed, you need to add id as a dependency for useEffect.

useEffect(() => {
  ....
}, [id, setPost]);

also, your post.tags will still be undefined, because the data comes after the component has finished rendering so you should actually check before that return if you have post data and if you don't have post data, to return null or a loading skeleton.

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

2 Comments

I've tried adding the dependencies as well, but the issue is that useEffect just doesn't seem to run on first render or otherwise. I've put console.logs in just about every possible place within the hook but none of them show up and there's no api request in the Network tab of my console. It's just... Not running. Also I was under the impression that the component wouldn't render until everything in the useEffect is resolved? At any rate, that doesn't seem to be the issue for the time being.
Never mind, it turns out that this was essentially the issue. The problem was I was forgot that empty objects are not falsy, so my attempts at conditionally rendering based on the presence of 'post' weren't working correctly. Problem solved. Cheers.

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.