Javascript 当我更改数据库时,为什么我的React应用程序在useEffect中运行firebase查询?
我的代码应该在第一次渲染时加载数据,所以我从firebase中提取了useEffect中的文档,并将它们存储在状态“data”中。它工作正常,所有的文档都按我的要求显示在页面上。现在我想通过单击每个文档下的按钮来删除单个文档。我是在deleteDoc函数的帮助下这样做的,该函数从数据库中删除文档(如果存在,则从存储器中删除文件)。删除工作正常,但删除成功后,“我的代码”会因某种原因再次从数据库重新加载数据,从而导致应用程序再次重新提交页面。我在useEffect中的两个不同位置登录了控制台,发现useEffect并没有执行其中的全部代码,只执行它从firebase获取数据的部分。我只希望它在后台执行该操作,而不会再次干扰数据状态。那么,如何在每次删除文档时停止重新抓取Javascript 当我更改数据库时,为什么我的React应用程序在useEffect中运行firebase查询?,javascript,reactjs,firebase,google-cloud-firestore,Javascript,Reactjs,Firebase,Google Cloud Firestore,我的代码应该在第一次渲染时加载数据,所以我从firebase中提取了useEffect中的文档,并将它们存储在状态“data”中。它工作正常,所有的文档都按我的要求显示在页面上。现在我想通过单击每个文档下的按钮来删除单个文档。我是在deleteDoc函数的帮助下这样做的,该函数从数据库中删除文档(如果存在,则从存储器中删除文件)。删除工作正常,但删除成功后,“我的代码”会因某种原因再次从数据库重新加载数据,从而导致应用程序再次重新提交页面。我在useEffect中的两个不同位置登录了控制台,发现
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);
});
};
根据这一点,我们可以使用onSnapshot
侦听集合中的更改,因此当您删除数据库中的文档时,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);
}
});
}
}, []);
通过调用
onSnapshot
从Firestore获取数据,您将附加一个永久侦听器。因此,当数据库发生更改时,确实希望再次调用回调(从而再次更新状态)
如果您只想,请使用get()
而不是onSnapshot()
:
嘿谢谢你的回答。我尝试了两种方法,但都不起作用。我认为出于某种原因,状态也会被刷新,因此在删除文档后,fetchData会再次设置为true。当我在onSnapshot方法中记录数据时,它显示一个空数组。想到这里发生了什么事,我的大脑都受了伤。。!嘿,老兄,非常感谢你!成功了。我不知道有没有固定的听众。只需要注意一件事:get()返回一个承诺,所以我不得不使用“.get()。然后((快照)=>{…})”它就成功了。很好的一点是@Akshat。我总是忘记
then()
:)两个都做了!
db.collection("files")
.orderBy("timeStamp", "desc")
.limit(5)
.get().then((snapshot) => {
...