javascript - 当我更改数据库时,为什么我的 React 应用程序在 useEffect 中运行 firebase 查询?
问题描述
我的代码应该在第一次渲染时加载数据,所以我在 useEffect 中从 firebase 获取文档并将它们存储在状态“数据”中。它工作正常,所有文档都按我想要的方式显示在页面上。现在我想通过单击每个文档下的按钮来删除单个文档。我是在 deleteDoc 函数的帮助下完成的,该函数从数据库中删除文档(如果存在,则从存储中删除文件)。删除工作正常,但删除成功后,我的代码由于某种原因再次从数据库重新加载数据,导致应用程序再次重新呈现页面。我在 useEffect 中的 2 个不同位置进行控制台登录,发现 useEffect 不会执行其中的整个代码,而只会执行它从 firebase 获取数据的部分。我只是希望它在后台执行该操作,而不会再次干扰数据状态。那么每次删除文档时如何停止重新获取呢?
const [data, setData] = useState([]);
useEffect(() => {
if (user) {
user.getIdTokenResult().then((idTokenResult) => {
setAdmin(idTokenResult.claims.admin);
});
db.collection("files")
.orderBy("timeStamp", "desc")
.limit(5)
.onSnapshot((snapshot) => {
console.log(data, "In query"); // This executes after the delete operation
setData(
snapshot.docs.map((doc) => {
return [doc.data(), { doc_id: doc.ref.id }];
})
);
});
}
console.log(data, "Outside query"); // This doesn't execute after the delete operation
}, []);
删除功能:
const deleteDoc = async (e, item) => {
e.preventDefault();
// Deleting file from storage if it exists
if (item[0].file_name) {
const deleteTask = storage
.ref("users/" + user.uid)
.child(item[0].file_name);
deleteTask
.delete()
.then(() => {
console.log("File deleted Successfully");
})
.catch((err) => console.log(err));
}
// Deleting document from firestore collection.
db.collection("files")
.doc(item[1].doc_id)
.delete()
.then(() => {
setData(
data.filter((doc) => {
return doc[1].doc_id !== item[1].doc_id;
})
);
console.log("Document successfully deleted!", data);
})
.catch((error) => {
console.error("Error removing document: ", error);
});
};
解决方案
根据this documentonSnapshot
,我们可以使用So,当您在db中删除文档时,我们可以监听集合中的更改,onSnapshot
将监听新的更改并在该函数内执行逻辑。
解决方案是分离监听器
const unsubscribe = db.collection("files")
.orderBy("timeStamp", "desc")
.limit(5)
.onSnapshot(() => {
// Respond to data
// ...
});
// Later ...
// Stop listening to changes
unsubscribe();
第二种解决方案是使用另一种状态,比如说fetchData
,一旦您收到有关负载的数据,请将其设置为false
如下所示:-
const [data, setData] = useState([]);
const [fetchData, setFetchData] = useState(true);
useEffect(() => {
if (user) {
user.getIdTokenResult().then((idTokenResult) => {
setAdmin(idTokenResult.claims.admin);
});
db.collection("files")
.orderBy("timeStamp", "desc")
.limit(5)
.onSnapshot((snapshot) => {
if(fetchData) {
setData(
snapshot.docs.map((doc) => {
return [doc.data(), { doc_id: doc.ref.id }];
})
);
setFetchData(false);
}
});
}
}, []);
推荐阅读
- javascript - 你如何避免两个鼠标点击事件从一个 div 注册到另一个?
- javascript - 将变量打印到文本区域而不是javascript中的控制台
- c# - 循环中的 C# .NET Core3 XHR 请求
- html - 更改输入类型 =“数字”的数字大小
- xml-parsing - 维基百科转储的结构是什么?
- objective-c - 使用 Core Graphics 在 macOS 上生成相关鼠标事件
- javascript - 在编译期间使用 js/jquery 从本地文件夹加载/自动填充所有图像
- linux - Linux - 如何用字符串替换文件名的最后几个字符
- flutter - 如何在颤振中创建子计时器?
- python-3.x - 无法使用 xpath 和 id 在网页中定位元素