具有Useeffect清理功能的Firebase

时间:2019-10-19 13:44:09

标签: javascript reactjs firebase use-effect

我正在尝试使用firebase集合的'public'参数获取所有数据,然后使用useffect,但控制台会报错。

我从firebase的文档中获取了以下结构: https://firebase.google.com/docs/firestore/query-data/get-data#get_multiple_documents_from_a_collection

,但控制台显示“警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务'

所以我转到了另一页: https://firebase.google.com/docs/firestore/query-data/listen#detach_a_listener

但是我不使用onSnapshot,除了firebase文档对我来说似乎是错误的,因为unsub不是函数。

useEffect(() => {

        let list = []

        const db = firebase.firestore().collection('events')
        let info = db.where('public', '==', 'public').get().then(snapshot => {
            if (snapshot.empty) {
                console.log('No matching documents.');
                setLoading(false)
                return;
            }
            snapshot.forEach(doc => {
                console.log(doc.id, "=>", doc.data())
                list.push({
                    id: doc.id,
                    ...doc.data()
                })
            })
            setEvents(list)
            setLoading(false)
        })
            .catch(error => {
                setLoading(false)
                console.log('error => ', error)
            })
        return () => info

    }, [])

2 个答案:

答案 0 :(得分:0)

您需要调用侦听器功能来分离和卸载。 https://firebase.google.com/docs/firestore/query-data/listen#detach_a_listener

useEffect(() => {

        let list = []

        const db = firebase.firestore().collection('events')
        let info = ...
        return () => info() # invoke to detach listener and unmount with hook

    }, [])

答案 1 :(得分:0)

您不需要清除.get(),就像普通的Fetch api调用一样。

您需要确保在setLoading

时仍可以装入组件。

示例:

// import useRef
import { useRef } from 'react'
// At start of your component
const MyComponent = () =>{
   const isMounted = useRef(false)
   useEffect(() => {
     isMounted.current = true;
     return () => isMounted.current = false;
  }, [])

   // Your query
   db.where('public', '==', 'public').get().then(snapshot => {
      if(isMounted.current){
        // set your state here. 
      }
   })

  return <div></div>
}