Background: This is a practice todo list app where I'm using onValue to listen to changes to the list of todos in realtime database, and then mapping that onto a tasks array in the front end.
I previously had a memory leak error appear when using onValue in the following manner - when I didn't unsubscribe from my onValue listener:
useEffect(
() => {
if (user) {
onValue(ref(database, `users/${user}/tasks`), (snapshot) => {
const todos = snapshot.val();
const tasks = [];
for (let id in todos) {
tasks.push({ ...todos[id], id: id })
}
setTasks(tasks)
})
} else {
setTasks([])
}
}, [user])
I saw from some other questions here that onValue returns an unsubscribe function, and I also saw an answer that by adding return to the onValue line, I could unsubscribe from it - I've tried to do this below:
useEffect(
() => {
if (user) {
return onValue(ref(database, `users/${user}/tasks`), (snapshot) => {
const todos = snapshot.val();
const tasks = [];
for (let id in todos) {
tasks.push({ ...todos[id], id: id })
}
setTasks(tasks)
})
} else {
setTasks([])
}
}, [user])
It seems to work for me, but could I get some help to confirm that this is the proper way to unsubscribe from this onValue listener?
CodePudding user response:
Your useEffect
callback needs to return an unsubscribe function, so that React can call that when the component/hook is no longer needed. By returning the return value from onValue
, you ensure that the onValue
gets unsubscribed when the component/hook is no longer needed. If that is what you want to accomplish (which seems the case), then this indeed looks correct.