'My component doesn't render for some reason

I'm trying to make sort of a twitter clone using react and in the Feed component, I am not able to render the tweets for some reason.

This is Home, the parent component of Feed. this is also where I call most of the relevant info from firebase.

function Home() {
  const[userInfo, setUserInfo] = useState({})
  const {user} = useUserAuth()
 
  useEffect(() => {
    const getUser = async()=>{ 
      const docRef = doc(db, "users", auth.currentUser.uid);
      const docSnap = await getDoc(docRef);
    
    if (docSnap.exists()) {
      
      setUserInfo(docSnap.data())
    } else {
      // doc.data() will be undefined in this case
    }}
    getUser()
   },[user]);

  return (
    <div className='cont-all'>
      <div className='menu'>
      <IconContext.Provider value={{className:"react-icons"}}>
        <ul>
          <li className='menu-option'><GrTwitter  color='rgb(14, 147, 255)' size={30}/></li>
          <li className='menu-option'><div className='hover-wrap'><AiFillHome size={23} ></AiFillHome>{window.innerWidth > 1200? "Home":null}</div></li>
          <li className='menu-option'><div className='hover-wrap'><BiMessageAltDetail size={23}></BiMessageAltDetail>{window.innerWidth > 1200? "Messages":null}</div></li>
          <li className='menu-option'><div className='hover-wrap'><AiOutlineUser size={23}></AiOutlineUser>{window.innerWidth> 1200? "Profile":null}</div></li>
        </ul>
        </IconContext.Provider>
        <SessionInfo user ={userInfo}/>
      </div>
      <div className='feed'>
        <CreateTweet username={userInfo.username} />
        {userInfo?<Feed user_info={userInfo}/>:null}
      
      </div>
      
      <div className='trends'>3</div>
    </div>
  )
}

This is the Feed component, parent of the Tweet components i'm trying to render multiple times depending on the number of posts i have stored.I'm storing the props in state in the first useEffect and the second useEffect is where I call all the tweets from firebase

function Feed({ user_info }) {
  const [tweets, setTweets] = useState([]);
  const [user,setUser] = useState({})
  
useEffect(()=>{
setUser(user_info)

},[user_info])



  useEffect(() => {
      const tweets_arr = []
      if (user.posts!==undefined && user.posts!==[]){
          const call = async (post)=>{
      const docRef = doc(db, "Twoots", post);
            const wanted_doc = await getDoc(docRef);
            tweets_arr.push(wanted_doc.data())
        }

      user.posts.forEach(element => {
          call(element)
      });
      setTweets(tweets_arr)
    }
     
 
  },[user]);





  return (
    <div>
      {tweets.map(item =>{return <Tweet  item={item} />})}
    </div>
  );
}

Finally this is the Tweet component. I don't think it's too relevant as it just receives data and displays it but i'll leave it here anyway

function Tweet(props) {
 
  
  return (
    <div className='tweet'>
      <div className='wrap-pfp-twt'>
      <div className='tw-pfp-cont1'><img  src='https://conteudo.imguol.com.br/c/esporte/96/2021/11/29/lionel-messi-atacante-do-psg-1638213496667_v2_4x3.jpg' className='tw-pfp' alt=""></img></div>
    <div>
      <div className='author-id'>@{props.item.username} . {props.item.likes}</div>
      <div className='actual-tweet'>{props.item.body}</div>
    </div>
    
    </div>
    <div className='interaction-bar'>
      <FaRegComment/><BsShare/><AiOutlineHeart/>
    </div>
    </div>
  )
}


Solution 1:[1]

Your tweets array is always going to be empty.

If you formatted your code correctly, this is what you'd see:

  useEffect(() => {
      const tweets_arr = []
      if (user.posts!==undefined && user.posts!==[]){
          const call = async (post)=> {
              const docRef = doc(db, "Twoots", post);
              const wanted_doc = await getDoc(docRef);
              tweets_arr.push(wanted_doc.data())
          }

          user.posts.forEach(element => {
              call(element)
          });

          setTweets(tweets_arr)
      }
  }, [user]);

Your problem is that the call() function is async. When you do a .forEach it does not wait for the async function to complete, so it immediately calls setTweets(tweets_arr). And since the .forEach has not completed, you will never see the tweets

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 gear4