Remove multiple firebase listeners at once

Im creating an app with react native and face the problem that I create multiple firebase listeners troughout the app, listeners on different screens to be precise and also listeners that listen to the firebase-database and others listening to the firestore.

What I want to accomplish is to kill all those listeners with one call or if necessary with multiple lines but as compact as possible - and also from an entire different screen where the listeners arent even running, this is important.

I know that there is the possibility to use Firebase.goOffline() but this only disconnects me from the Firebase - it doesnt stop the listeners. As soon as I goOnline() again, the listeners are all back.

I didnt find any solution yet for this problem from google etc thats why I try to ask here now, I would appriciate if anybody would have an idea how maybe an approach how to handle this type of behavior.

The following code samples provide you with listeners I included inside my app, they are located in in the same screen but I have nearly identical ones in other screens.

Database listener:

const statusListener = () => {
        var partnerRef = firebase.database().ref(`users/${partnerId}/onlineState`);
        partnerRef.on('value', function(snapshot){
            setPartnerState(snapshot.val())
        })
    };

Firestore Listener: (this one is very long, thats only because I filter the documents I retrieve from the listener)

const loadnewmessages = () =>{ firebase.firestore().collection("chatrooms").doc(`${chatId}`).collection(`${chatId}`).orderBy("timestamp").limit(50).onSnapshot((snapshot)  => {
            var newmessages = [];
            var deletedmesssages = [];
            snapshot.docChanges().forEach((change) => {
                if(change.type  === "added"){
                    newmessages.push({
                        counter: change.doc.data().counter,
                        sender: change.doc.data().sender,
                        timestamp: change.doc.data().timestamp.toString(),
                        value: change.doc.data().value,
                        displayedTime: new Date(change.doc.data().displayedTime)
                    })
                };
                if(change.type  === "removed"){
                    deletedmesssages.push({
                        counter: change.doc.data().counter,
                        sender: change.doc.data().sender,
                        timestamp: change.doc.data().timestamp.toString(),
                        value: change.doc.data().value,
                        displayedTime: new Date(change.doc.data().displayedTime)
                    })
                };

            })
            if(newmessages.length > 0){
                setChatMessages(chatmessages => {
                    return chatmessages.concat(newmessages)
                });
            };
            if(deletedmesssages.length > 0){
                setChatMessages(chatmessages => {
                    var modifythisarray = chatmessages;
                    let index = chatmessages.map(e => e.timestamp).indexOf(`${deletedmesssages[0].timestamp}`);
                    let pasttime = Date.now() - parseInt(modifythisarray[index].timestamp);
                    modifythisarray.splice(index, 1);
                    if(pasttime > 300000){
                        return chatmessages
                    }else{
                        return modifythisarray
                    }
                });
                setRefreshFlatList(refreshFlatlist => {
                    //console.log("Aktueller Status von refresher: ", refreshFlatlist);
                    return !refreshFlatlist
                });
            }
            newmessages = [];
            deletedmesssages = [];
        })
    };

Both those listeners are called within a useEffect hook just like that: (useEffect with empty braces at the end makes sure those listeners are called only once and not multiple times.)

useEffect(() => {
        loadnewmessages();
        statusListener();
    }, []); 

Upvotes: 0

Views: 800

Answers (1)

Daniel Duong
Daniel Duong

Reputation: 1104

All of the subscribe functions return the unsubscribe function

const unSubscriptions = [];

... Where you subscribe
const unSub = document.onSnapshot(listener);
subscriptions.push(unSub);

... Where you unsubscribe all
function unSubAll () {
   unSubscriptions.forEach((unSub) => unSub());
   // Clear the array
   unSubscriptions.length = 0;
}

Upvotes: 4

Related Questions