我目前正在 React 中创建一个待办事项列表,该列表从 Firestore 检索任务并使用状态钩子将它们本地存储在数组中:const [todoList, setTodoList] = useState([])
.我在编写代码时遇到了一些障碍,主要是因为 Firestore 的onSnapshot
函数似乎无法与 React 一起正常运行。快照代码在加载(以检索现有任务(和创建新任务时调用。用于将更改追加到数组的快照代码为:
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
});
当我尝试不同的变体时,会弹出一些问题(推送到空数组,然后将两个数组连接在一起等(:
待办事项列表状态不会在新快照上保留。例如,创建一个新任务
task2
将 todoList 更新为[task2]
,但在此之后task3
创建另一个任务会使第一个任务消失并将数组更新为[task3]
而不是[task2, task3]
。onSnapshot 会不断检索相同的任务,尽管它们之前被检索过。例如,在加载时,初始待办事项列表将更新为
[task1, task2, task3]
。创建新任务并再次调用快照函数时,我希望将 todoList 更新为[task1, task2, task3, task4]
。但是,相反,每当再次调用快照函数时,我都会返回一些[task1, task2, task3, task1, task2, task3, task4]
复合的变体。
这个问题似乎只发生在 React 中,而不是原生 JavaScript(任务的创建和检索很好,没有任何重复项(。我尝试过的一些解决方案是将所有内容包装在 onEffect 中(我相信如果我不将todoList
作为依赖项传递,这给了我第一个问题,如果我这样做了,就会无限循环(并通过unsubscribe()
调用快照函数(这仍然给了我第二个问题(。
解决了!我将所有内容嵌套在没有依赖项的useEffect中,并设法解决了有关状态未正确更新的第一个要点。我不是通常使用setTodoList(todoList.concat(newTasks))
设置状态,而是使用setTodoList(currentList => currentList.concat(newTasks))
在功能上设置状态(关于 setState 关于 useState 的异步,异步不是我的专长(。在这里找到答案:https://stackoverflow.com/a/56655187/9477642。
这是最终的快照更新代码(我不知何故也解决了 onSnapshot 返回整个集合的问题,而不仅仅是每次都更改,但我忘记了如何,如果我记得为什么,我会更新它(:
useEffect(() => {
let unsubscribe = todoReference.onSnapshot(colSnapshot => {
console.log(colSnapshot.docChanges());
let newTasks = [];
colSnapshot.docChanges().forEach(change => {
if (change.type === 'added') {
const taskData = change.doc.data();
newTasks.push(taskData);
}
});
setTodoList(currentList => currentList.concat(newTasks));
});
return () => unsubscribe();
}, []);