2

My useEffect is getting data from web api. I want to render all posts on home page and trigger again my useEffect when someone create new post. The problem is when I put dependancy on useEffect its start doing endless requests. When I pass empty array as dependancy , when someone create new post it doesnt render on home page until I refresh the page. I read a lot in internet about that problem but still I dont know how to do it. Thanks

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

  useEffect(() => {
    const jwt = localStorage.getItem("jwt");

    fetch('https://localhost:44366/api/Posts/getAllPosts',
      {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          'Authorization': 'Bearer ' + jwt
        },
      })
      .then(r => r.json()).then(result => setPosts(result));
  }, [posts]);


  return (
    <div >
      <Router>
        <Header />
        <main className="App">
          {
            posts.map(post => (
              <Post keyToAppend={post.CreatedOn} username={post.User.FirstName} title={post.Title} content={post.Content} images={post.ImageUrls} avatarImage={post.User.MainImageUrl} />
            ))
          }
        </main>
      </Router>
      <Footer />
    </div>
  );
}

Post component :

const Post = ({ keyToAppend, username, title, content, images, avatarImage }) => {
    return (
        <div className="post" key={keyToAppend}>
            <div className="post__header">
                <Avatar
                    className="post__avatar"
                    alt="avatar"
                    src={avatarImage}
                />
                <h3 className="username">{username}</h3>

            </div>
            <h1 className="title">{title}</h1>
            <p className="content">{content}</p>
            <p>
                {typeof images != "undefined" ? <ImageSlider slides={images} /> : ""}
            </p>
        </div>
    )
}


export default Post;

1 Answer 1

5

Remove posts from the dependency array, so it's just []. That will run the effect once, when the component loads.

useEffect(() => {
  const jwt = localStorage.getItem("jwt");

  fetch('https://localhost:44366/api/Posts/getAllPosts',
    {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        'Authorization': 'Bearer ' + jwt
      },
    })
    .then(r => r.json()).then(result => setPosts(result));
}, []);
// ^^−−−−− remove `posts` here

The reason it runs endlessly with your current code is that your effect callback changes the posts state member, which triggers the effect again (because posts is in the dependency array). You only need to include things in the dependency array that you read in the effect callback. You never read posts in the effect callback.


Side note: That code is falling prey to the fetch API footgun I describe here. You need to check r.ok before calling r.json (and handle errors):

useEffect(() => {
    const jwt = localStorage.getItem("jwt");

    fetch("https://localhost:44366/api/Posts/getAllPosts", {
        method: "GET",
        headers: {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + jwt
        },
    })
    .then(r => {
        if (!r.ok) { // <=================
            throw new Error(`HTTP error ${r.status}`);
        }
        return r.json();
    })
    .then(result => setPosts(result))
    .catch(error => {
        // ...handle/report error here...
    });
}, []);
Sign up to request clarification or add additional context in comments.

2 Comments

I understand everything you said except "You only need to include things in the dependency array that you read in the effect callback.". I need to include in dependancy array props that Post component recieves or ? Sorry, but still dont get it.
@koceww - Nothing in the callback uses posts, so you shouldn't list posts in the dependency array. More: reactjs.org/docs/hooks-reference.html#useeffect

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.