Firebase onstoreshot的cleanup()在useEffect()中不起作用

时间:2020-01-22 08:37:29

标签: reactjs firebase google-cloud-firestore react-hooks react-router-dom

我有一个React项目,该项目使用onSnapshot()侦听器列出了Firestore中的数据。

一切正常,但是当我导航到新页面时(该页面也具有与上一页相同的列表,但具有不同的数据),上一列表中的数据仍显示在新页面上。仅当我单击某处的页面时,才会显示新数据。

示例:

/home显示我的帖子列表。

/friends显示了我的朋友列表。

当我从/friends中单击/home时,仍然看到我的帖子列表。

我试图像这样卸载监听器:

  useEffect(() => {

      const posts = firebase
        .firestore()
        .collection('posts')
        .onSnapshot(function(querySnapshot) {

          var postsArray = [];

          querySnapshot.forEach(doc => {
              postsArray.push(doc.data());
          });

      setServiceProviderArray(postsArray);

      return function cleanup() {
          posts()
    };

  }, []);

但这并不能解决问题。

我正在使用React-Router-Dom进行路由。

这里有什么我想念的吗? 非常感谢。

2 个答案:

答案 0 :(得分:3)

很高兴获得“沙盒”示例或一些东西来了解您完成的实现的样子。既然有很多方法可以做到。

您所能做的就是让侦听器挂上钩子,以在每次您希望通过新条件获取数据时启动使用效果。

const [query, setQuery] = React.useState("posts");


  useEffect(() => {

      const posts = firebase
        .firestore()
        .collection(query)
        .onSnapshot(function(querySnapshot) {

          var postsArray = [];

          querySnapshot.forEach(doc => {
              postsArray.push(doc.data());
          });

      setServiceProviderArray(postsArray);

      return posts.unsubscribe();
    };

  }, [query]);

这样,每次您使用setQuery()时,postsArray都会重新填充。

希望有帮助

答案 1 :(得分:2)

这有点令人困惑:

 return function cleanup() {
          posts()
    };

您期望cleanup()做什么?

在这种情况下,return () => posts();位将在卸载组件时取消订阅您的实时侦听器。这只是意味着,如果在卸载组件时Firestore数据库发生了更改,则不会获得新数据的更新。很好,请不要更改您在这里所做的事情。如果您不取消订阅,即使该组件不在页面上,您仍将获得更新,并且最终会导致内存泄漏。 https://firebase.google.com/docs/firestore/query-data/listen#detach_a_listener

上的更多有关分离侦听器的信息

听起来您要卸载的数据就是清除数据。为此,您必须编写一个清除它的函数。 setServiceProviderArray的功能相反。这样可以清除服务提供者数组。然后,您想在卸载时呼叫。也许setServiceProviderArray([]);所以...

return () => {
  posts()
  clearServiceproviderArray()
};

也许setServiceProviderArray([])可以工作。如果这样做不能解决问题,请共享setServiceProviderArray()的代码,我们可以通过编写相反的功能来帮助您创建clearServiceproviderArray()