javascript - REACT + FIRESTORE :监听 react 组件中 firebase 集合的变化以自动更新反应状态
问题描述
我在firestore中有一个帖子集合,我从中获取列表[user1,user2,...]中用户创建的所有帖子。我可以在下面的方法中使用 onSnapshot 来监听集合的变化:
export default function Feed({ friendList }) {
// currentUser context
const { currentUser } = useAuth();
// array to save posts from database
const [posts, setPosts] = useState([]);
// function to fetch data from database
useEffect(() => {
db.collection('posts')
.where('userId', 'in', [...friendList])
.orderBy('timestamp', 'desc')
.onSnapshot((snapshot) => {
setPosts(
snapshot.docs.map((doc) => ({
id: doc.id,
post: doc.data(),
}))
);
});
}, []);
return (
<div className='feed'>
{currentUser ? (
<div className='feed_container'>
{posts.map(({ id, post }) => {
return (
<Post
key={id}
id={id}
userProfileURL={post.userProfileURL}
username={post.username}
displayName={post.displayName}
photoURL={post.photoURL}
/>
);
})}
</div>
但是如果friendList 有超过10 个元素,这个'in' 查询将不起作用。因此,我可以使用以下承诺从收集中获取所需的文件:
useEffect(() => {
getPostsFromFriendsList(friendList);
}, []);
async function getPostsFromFriendsList(friendList){
const promises = [];
for (let i = 0; i < friendList.length; i++) {
promises.push(getPosts(friendList[i]));
}
const postsForHomeFeed = await Promise.all(promises);
const array = [];
for (let i = 0; i < postsForHomeFeed.length; i++) {
postsForHomeFeed[i].docs.map((doc) => {
array.push({
id: doc.id,
post: doc.data(),
});
});
}
setPosts(array);
}
function getPosts(userId) {
return new Promise((resolve, reject) => {
db.collection('posts')
.where('userId', 'in', [userId])
.onSnapshot((snapshot) => {
resolve(snapshot);
});
});
}
但是,如果在我的 firestore 集合中添加或删除了帖子,我不再可以监听数据库中的更改来更新我的反应状态以相应地呈现。如何在第二个代码中为 Promise 解决方案设置我的 useEffect 以便我可以在每次 firestore 集合发生变化时更新我的反应状态?谢谢你。
解决方案
您需要让监听器保持打开状态,并在每次触发它们时更新状态,并根据 post 合并数据,id
如下所示:
useEffect(() => {
getPostsFromFriendsList(friendList);
}, []);
//source: https://stackoverflow.com/questions/7146217/merge-2-arrays-of-objects
const merge = (a, b, prop) => {
var reduced = a.filter(
(aitem) => !b.find((bitem) => aitem[prop] === bitem[prop])
);
return reduced.concat(b);
};
async function getPostsFromFriendsList(friendList) {
const promises = [];
for (let i = 0; i < friendList.length; i++) {
db.collection("posts")
.where("userId", "in", [friendList[i]])
.onSnapshot((snapshot) => {
const array = [];
snapshot.docs.map((doc) => {
array.push({
id: doc.id,
post: doc.data(),
});
});
setPosts(merge([...posts], array, "id"));
});
}
}
推荐阅读
- python - 相似矩阵聚类
- c# - 将多个空格从文本文件拆分为数组
- javascript - 显示过去 2 周(vue.js)
- aws-lambda - 有条件地将 Item 放入 DynamoDB
- spring-boot - Spring Integration - 多播 UDP 消息未更新
- java - JScrollPane 上的 JButton
- javascript - 从数组中显示表内人员
- markdown - 在 Reveal MD 中禁用自动填充缺少的 HTML 结束标记
- django - 如何从另一个表 django rest 框架中获取相关数据
- firebase - 使用当前用户在 Flutter App 中更新 Firebase 时出现问题