How do I go about this? I can't figure it out from anything else I can find on here.
Background
I have collections in the Firestore for posts
and users
. The information is going to be rendered out in to a Posts components displaying all of the existing posts on the dashboard.
Users Collection
users
holds an avatar
property which stores an image URL. The doc id for each user is just their username as these are unique.
Posts Collection
posts
have an author
property which is exactly the same as the username
/doc.id
The Aim
When iterating through the posts
I want to push them to an array and store their id
and the rest of the post
data. I also need to relate this to the users
collection and with each iteration, find the avatar
of the user
that matches the post author
.
Things I've already tried
I have tried using async/await
within the forEach
loop, using the post.author
value to get the correct user document
and pulling the avatar
.
Posts
component code
import { useEffect, useState } from "react"
import { Link } from "react-router-dom"
import { collection, onSnapshot /*doc, getDoc*/ } from "firebase/firestore"
import { db } from "lib/firebase"
import AllPostsSkeleton from "components/Skeletons/AllPostsSkeleton"
import Tags from "components/Tags"
import defaultAvatar from "assets/images/avatar_placeholder.png"
const Posts = () => {
const [loading, setLoading] = useState(true)
const [posts, setPosts] = useState(null)
useEffect(() => {
const unsubscribe = onSnapshot(
collection(db, "posts"),
(docs) => {
let postsArray = []
docs.forEach((post) => {
// const docRef = doc(db, "users", post.author)
// const docSnap = await getDoc(docRef)
postsArray.push({
id: post.id,
// avatar: docSnap.data().avatar,
...post.data(),
})
})
setPosts(postsArray)
},
(error) => {
console.log(error)
}
)
setLoading(false)
return () => unsubscribe()
}, [])
if (loading) return <AllPostsSkeleton />
if (!posts) return <div className="no-posts">No posts to show</div>
const RenderPosts = () => {
const sortedPosts = posts.sort((a, b) => {
return new Date(b.date.seconds) - new Date(a.date.seconds)
})
return sortedPosts.map(
({ id, author, slug, content, tags, comment_count, avatar }) => (
<article className="post-preview media" key={id}>
<figure className="media-left">
<p className="comment-avatar image is-96x96">
<img src={avatar || defaultAvatar} alt={content.title} />
</p>
</figure>
<div className="media-content">
<div className="content">
<header className="post-header">
<h2 className="title is-3">
<Link to={`/user/${author}/posts/${slug}`}>
{content.title}
</Link>
</h2>
<div className="tags">
<Tags data={tags} />
</div>
</header>
<p className="post-excerpt">{content.excerpt}</p>
<footer className="post-footer">
Posted by
<Link to={`/user/${author}`} className="capitalise">
{author}
</Link>
| <Link to={`/user/${author}/posts/${slug}`}>View Post</Link>
</footer>
<div className="content">
<Link to={`/user/${author}/posts/${slug}#comments`}>
Comments ({comment_count})
</Link>
</div>
</div>
</div>
</article>
)
)
}
return (
<div className="posts-list">
<RenderPosts />
</div>
)
}
export default Posts