首页 > 解决方案 > 当我更改数据库时,为什么我的 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);
      });
  };

标签: javascriptreactjsfirebasegoogle-cloud-firestore

解决方案


根据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);
          }
        });
     }
   }, []);

推荐阅读