0

Hi I'm trying to make a twitter clone app. I am using React on the client side and Express on the server side and PostgreSQL as my database. So here's the problem, I'm trying to use the useEffect like this:

const [tweets, setTweets] = useState([]);
  const getTweets = async () => {
    const res = await api.get("/posts", {
      headers: { token: localStorage.token },
    });
    setTweets(res.data);
  };
  useEffect(() => {
    getTweets();
  }, [tweets]);

I have no idea why it's looping infinite times, am I using it correctly though? I want the tweets to be updated every time I post a tweet. It's working fine but it's running infinite times. I just want it to re-render if a tweet got posted.

Here's my server code for getting all the posts:

async all(request: Request, response: Response, next: NextFunction) {
    return this.postRepository.find({
      relations: ["user"],
      order: {
        createdAt: "DESC",
      },
    });
  }

3 Answers 3

1

The problem is every time you change the tweets it executes useEffect and changes the tweets and so long and so forth, so it's natural that it loops infinitely, the solution is to add a trigger that you set to true when a tweet gets posted, so the solution would be like this

const [tweets, setTweets] = useState([]);
const [isFetching, setIsFetching] = useState(false);
  const getTweets = async () => {
    const res = await api.get("/posts", {
      headers: { token: localStorage.token },
    });
    setTweets(res.data);
  };

  useEffect(() => {
    getTweets();
    setIsFetching(false);
  }, [isFetching]);

and set some logic to use setIsFetching(true) in order to execute the useEffect

PS: if you use an empty array in useEffect, it would execute only when the component is mounted (at the start)

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

2 Comments

Oh I understand now. Thanks for explaining! But is this the best practice if I'm trying to implement a newsfeed (tweets) with useEffect?
Yes, this is what you should use for any real time data fetching from the api for all kinds of lists including tweets!
0
useEffect(() => {
    getTweets();
  }, [tweets]); // [tweets means that hook works every time 'tweets' state changes]

so your getTweets function set tweets => as tweets are changed hook works again => call getTweets => ... = infinite loop

if you want to download tweets, use empty array instead - hook will work once then

2 Comments

sorry i can't comprehend your explanation :( but i get it now though
I wrote the same thing as a guy above - you had wrong dependencies list within your hook.
0

Pass empty array as a second arg for calling it once otherwise for changing it on every tweet change it will re-trigger, so whenever state will change only then it will be re-rendered like Tarukami explained. One thing you can do is check the length like mentioned below so not to compare the whole object but just the length

useEffect(() => {
    getTweets();
  }, [tweets.length]);

This might raise an error react-hooks/exhaustive-deps lint error (that's a bypass you can use it). But if you want more tighter check you can compare the ids on each re-render (create a hash/key/id from all element in the array and compare them on each render) like so [tweet id here]) // Only re-subscribe if id changes

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.