I'm currently creating a to-do list within React which retrieves tasks from Firestore and stores them locally within an array using state hooks: const [todoList, setTodoList] = useState([])
. I've run into some roadblocks while coding this mainly because Firestore's onSnapshot
function doesn't seem to play properly with React. The snapshot code is called on load (to retrieve existing tasks) and when a new task is created. The snapshot code for appending changes to an array is:
todoReference.onSnapshot(colSnapshot => {
colSnapshot.docChanges().forEach(change => {
if (change.type === 'added') {
const taskData = change.doc.data();
todoList.push(taskData);
}
});
setTodoList(todoList); // "update state" using new array
});
There are a few issues which pop-up when I try different variations of this (pushing to empty array and then concatenating the two arrays together, etc.):
The todo list state doesn't persist on new snapshot. For example, creating a new task
task2
updates the todoList to[task2]
, but creating another tasktask3
after that makes the first task disappear and updates the array to[task3]
instead of[task2, task3]
.onSnapshot keeps retrieving the same tasks despite them being previously retrieved. For example, on load the initial todoList is updated to
[task1, task2, task3]
. When creating a new task and calling the snapshot function again, I expect the todoList to be updated to[task1, task2, task3, task4]
. However, instead I'm returned some variation of[task1, task2, task3, task1, task2, task3, task4]
which compounds whenever the snapshot function is called again.
This issue seems to only happen in React and not native JavaScript (the tasks are created and retrieved just fine without any duplicates). Some solutions I have tried is wrapping everything within a onEffect (which I believe gave me the first problem if I didn't pass todoList
as a dependency, and if I did would infinitely loop) and calling the snapshot function via unsubscribe()
(which still gave me the second problem).