In my webapp with Firestore (Firebase 9) I have the following code which should turn off a realtime listener based on the argument in the getRecentProfilesExternal() function. It works in ACTION1 but not in ACTION2.
Strangely, I get the "unsubscribed" alert in ACTION2 although the listener remains active.
Thanks for any help!
//Get profiles and update them in realtime
//The command param determines if the function should subscribe to changes (leave the onSnapshot listener on),
//or unsubscribe (in order to limit Firestore reads), usually when another listener is turned on instead
const getRecentProfilesExternal = (command) => {
//Get loggedin user data
const auth = getAuth();
onAuthStateChanged(auth, (user) => {
if (user) {
//Get last 20 profiles: initial render and listen to changes
const qProfiles = query(collection(db, "candidateprofiles"), where("useridprimary", "==", store.state.currentUserId));
//initial data fetch and listen to Firestore collection changes
const unsubscribe = onSnapshot(qProfiles, (snapshot) => {
store.state.currentProfileList = []
snapshot.docs.forEach((doc) => {
let profile = doc.data()
profile.id = doc.id
store.state.currentProfileList.push(profile)
})
})
//ACTION 1
setTimeout(() => {
unsubscribe()
}, 5000);
//ACTION 2
if(command == "unsubscribe") {
//this turns the onSnapshot listener off
unsubscribe()
alert("unsubscribed")
}
else {
//do nothing, this will keep the onSnapshot listener turned on
}
} else {
//user not signed in
}
});
}
So I just realised that when I call the function a second time, it subcribes, then ubsubscribes to a new listener. But the old listener is still active. So now my problem was how to fire unsubscribe() later, when the function has already run a first time to turn the listener on. I didn't have access to unsibscribe() outside of the function.
So I solved it by declaring a global variable called unsubscribeToRecentProfiles. This variable is then assigned the onSnapshot code in the initial function. Now I can create a second function that runs the unsubscribe as it has global scope. Not very elegant but I don't see a better way right now. This is my solution:
let unsubscribeToRecentProfiles;
//Get profiles and update them in realtime
const getRecentProfiles = () => {
//Get loggedin user data
const auth = getAuth();
onAuthStateChanged(auth, (user) => {
if (user) {
const qProfiles = query(collection(db, "candidateprofiles"), where("useridprimary", "==", store.state.currentUserId));
unsubscribeToRecentProfiles = onSnapshot(qProfiles, (snapshot) => {
store.state.currentProfileList = []
snapshot.docs.forEach((doc) => {
let profile = doc.data()
profile.id = doc.id
store.state.currentProfileList.push(profile)
})
})
} else {
//user not signed in
}
});
}
unsubscribeToRecentProfiles()