Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 当我更改数据库时,为什么我的React应用程序在useEffect中运行firebase查询?_Javascript_Reactjs_Firebase_Google Cloud Firestore - Fatal编程技术网

Javascript 当我更改数据库时,为什么我的React应用程序在useEffect中运行firebase查询?

Javascript 当我更改数据库时,为什么我的React应用程序在useEffect中运行firebase查询?,javascript,reactjs,firebase,google-cloud-firestore,Javascript,Reactjs,Firebase,Google Cloud Firestore,我的代码应该在第一次渲染时加载数据,所以我从firebase中提取了useEffect中的文档,并将它们存储在状态“data”中。它工作正常,所有的文档都按我的要求显示在页面上。现在我想通过单击每个文档下的按钮来删除单个文档。我是在deleteDoc函数的帮助下这样做的,该函数从数据库中删除文档(如果存在,则从存储器中删除文件)。删除工作正常,但删除成功后,“我的代码”会因某种原因再次从数据库重新加载数据,从而导致应用程序再次重新提交页面。我在useEffect中的两个不同位置登录了控制台,发现

我的代码应该在第一次渲染时加载数据,所以我从firebase中提取了useEffect中的文档,并将它们存储在状态“data”中。它工作正常,所有的文档都按我的要求显示在页面上。现在我想通过单击每个文档下的按钮来删除单个文档。我是在deleteDoc函数的帮助下这样做的,该函数从数据库中删除文档(如果存在,则从存储器中删除文件)。删除工作正常,但删除成功后,“我的代码”会因某种原因再次从数据库重新加载数据,从而导致应用程序再次重新提交页面。我在useEffect中的两个不同位置登录了控制台,发现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);
      });
  };
根据这一点,我们可以使用
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) => {
    ...