Reputation: 443
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
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