1

I'm trying to create a Twitter clone, and I'm having troubles with my news feed. Basically it pulls tweets from my firebase database for each user followed by the current user. So say you follow Jon Abrahams and Terry Crews, for each of these 2, it'll pull the "tweets" collection, and for each tweet, it'll return the data.

I did this with useState and useContext ( since I needed Context and couldn't make it work in a class component, but also needed state ).

  const CurrentUser = useContext(CurrentUserContext);
  const [tweets, setTweets] = useState({tweets: []});

  const feedTheFeed = async (id) => {
  const followedUsers = await getFollowedUsers(id);

  if(followedUsers) {
    followedUsers.docs.forEach(async doc => {
      const followedId = doc.data();
      const unformatTweets = await getTweetsByUser(followedId.follows);

      if(unformatTweets.docs) {
        unformatTweets.docs.map(unformatTweet => {
          const tweetText = unformatTweet.data();

          setTweets({
            tweets: [...tweets, tweetText]
          })
          // console.log(tweetText);
        })
      }
    })

    // console.log(tweets);
  }

  }

  useEffect(() => {
    if(!CurrentUser) return;

    if(CurrentUser.id || CurrentUser.uid) {
      feedTheFeed(CurrentUser.id);
    }
  }, [CurrentUser]);

The problem is that there's an issue when loading the component, it says that "tweets is not iterable", but it's an array, so I don't see why it wouldn't work. Does anyone have an idea ?

Thank you !

4
  • 5
    It's not an array; the initial value is { tweets: [] }, so tweets is an object and tweets.tweets is the array. Commented Jul 5, 2020 at 22:27
  • Right, no idea why I added "tweet" when setting the default value.. I changed it, and now I get only one item in the array when logging the tweets in the return() statement, I had that problem earlier when trying different things Commented Jul 5, 2020 at 22:36
  • If you log it right after setTweets you're still seeing the old value; it's not updated until the component re-renders and useState is called again. Commented Jul 5, 2020 at 22:37
  • I'm logging it in the return() statement at the end when displaying the component, there's a first item, and on the next loop the tweet replaces the previous one Commented Jul 5, 2020 at 22:40

2 Answers 2

3

Seems like what you want is

const [tweets, setTweets] = useState([]);

and

setTweets([...tweets, tweetText])
Sign up to request clarification or add additional context in comments.

5 Comments

That makes sense, thanks ! Though now I always get one item in the array when I console.log() it in the return() part of the component
upvote you, but I think better use callback: setTweets(oldTweets => [...oldTweets , tweetText]);
It’s late here so I’m leaving it for today, I’ll try the prevTweets thing tomorrow, I knew this for setState but didn’t know if could be used with hooks, thanks
@Omer, if I'm not mistaken, that code doesn't work because it will set 'tweets' to be a function.
0

I think what you want to do is this.....

const [tweets, setTweets] = useState([]);

setTweets(b => [...b, tweetText])

1 Comment

When adding answer to an old question (13 months ago), consider reading other's answer before posting yours. Your answer has been included here.

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.