'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 |
