cleanup() 在使用 Firebase Firestore onSnapshot 的 useEffect() 中不起作用

Posted

技术标签:

【中文标题】cleanup() 在使用 Firebase Firestore onSnapshot 的 useEffect() 中不起作用【英文标题】:cleanup() not working in useEffect() with Firebase Firestore onSnapshot 【发布时间】:2020-05-08 08:51:36 【问题描述】:

我有一个 React 项目,它使用 onSnapshot() 侦听器列出来自 Firestore 的数据。

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

例子:

/home 显示我的帖子列表。

/friends 显示我的朋友列表。

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

我尝试这样卸载监听器:

  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 进行路由。

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

【问题讨论】:

【参考方案1】:

这有点令人困惑:

 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()

【讨论】:

如果我在调用 setServiceProviderArray(posts) 之前将超时设置为 500 毫秒,它似乎可以工作。 那是因为新数据覆盖了旧数据。如果这对你有用,那很好,但我不确定你的问题是什么。那么,打电话给你的清理工作也是一种误导。您应该将其称为取消订阅或分离。除非您编写清理函数,否则您不会清理任何东西。【参考方案2】:

如果能得到一个沙盒示例或其他东西来看看你所做的实现是什么样子的,那就太好了。因为有很多方法可以做到。

您可以做的是与侦听器挂钩,以便在您每次需要新标准的数据时启动useEffect

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都会被重新填充。

【讨论】:

以上是关于cleanup() 在使用 Firebase Firestore onSnapshot 的 useEffect() 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 不刷新令牌

如何在android的firebase中执行快速搜索[关闭]

使用 Wordpress 用户或数据库验证 Firebase/Firechat

面向匿名用户的 Firebase 推送网络通知

没有从firebase接收推送通知

使用来自 REST API 的令牌的 Firebase 登录