Firebase with useeffect cleanup function

Viewed 3218

I'm trying to get all data with the 'public' parameter of a firebase collection and then use useffect, but the console accuses error.

I took this structure from firebase's documentation: https://firebase.google.com/docs/firestore/query-data/get-data#get_multiple_documents_from_a_collection

but the console says 'Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function'

So I went to this other page: https://firebase.google.com/docs/firestore/query-data/listen#detach_a_listener

But I'm not using onSnapshot, besides firebase documentation seems wrong to me, since unsub is not a function.

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 Answers

You don't need to clear a .get(), it's like a normal Fetch api call.

You need to make sure your component is still mounted when you setLoading

Example:

// 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>
}
Related