Nerbelwerzer
Nerbelwerzer

Reputation: 13

useEffect not running at all when navigating to page with React Router

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?

Upvotes: 0

Views: 3020

Answers (1)

Eek
Eek

Reputation: 1750

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.

Upvotes: 1

Related Questions