在您的 map 函数中,您不会返回文档的数据。
setComments(snapshot.docs.map((doc) => {
doc.data(); // <-- not returned!
}));
这意味着对于您在帖子中拥有的尽可能多的 cmets,您只会得到一个该长度的空数组。即 3 cmets -> setComments([undefined, undefined, undefined])
您可以通过将该指令重写为以下之一来解决此问题:
setComments(snapshot.docs.map((doc) => {
return doc.data()
}));
setComments(snapshot.docs.map(
(doc) => doc.data()
));
setComments(snapshot.docs.map((doc) => doc.data()))
但是,当您处理一个 cmets 数组时,您还应该返回数据中每个评论的文档 ID,以便您可以将其用作 key for rendering。
setComments(snapshot.docs.map(
(doc) => ({ key: doc.id, ...doc.data() })
));
其他说明
不要同时使用doc() 和collection():
const posts = doc(db, "posts", postId);
const comment_list = collection(posts, "comments");
您可以单独使用collection():
const comment_list = collection(db, "posts", postId, "comments");
这会将你的函数变成:
const fetchComments = async () => {
const comment_list = collection(db, "posts", postId, "comments");
const snapshot = await getDocs(comment_list);
setComments(snapshot.docs.map(
(doc) => ({ key: doc.id, ...doc.data() })
));
}
为了使其在 React 中使用更安全,您应该将其包装在 useEffect 中,以确保在获得数据后调用 setComments 仍然有效。
useEffect(() => {
let unsubscribed = false;
if (!postId) {
console.error(`Failed to load post comments! postId (${postId}) was falsy`);
setComments(null);
setLoading(false);
setErrorMessage("Invalid post ID");
return;
}
const comment_list = collection(db, "posts", postId, "comments");
setLoading(true);
getDocs(comment_list)
.then((comment_list_snapshot) => {
if (unsubscribed) return; // silently discard, outdated
setComments(comment_list_snapshot.docs.map(
(doc) => ({ key: doc.id, ...doc.data() })
));
setErrorMessage(null);
setLoading(false);
})
.catch((err) => {
if (unsubscribed) return; // silently discard, outdated
console.error("Failed to load post comments!", err);
setComments(null);
setErrorMessage("Comments could not be loaded.");
setLoading(false);
});
return () => unsubscribed = true;
}, [db, postId]);
除了您设置的数据考虑使用 Firebase 挂钩库或编写您自己的数据之外,对于大多数 Firestore 调用,上述块看起来都一样,因此您可以将其全部展平为:
const [ comments_docs, comments_loading, comments_error ] = useFirestoreCollection(db, "posts", postId, "comments")
if (comments_loading)
return null; // hide until loaded
if (comments_error) {
console.error("Failed to load comments: ", comments_error);
return (<div class="error">Could not load comments</div>)
}
const comments = comments_docs.map((doc) => ({ key: doc.id, ...doc.data() }));
return ({
comments.map((commentData) => {
return <Comment
key={commentData.key}
author={commentData.author}
content={commentData.content}
...
/>
})
});