Firestore onSnapshot 通过 onEffect 中的状态附加到数组

IT技术 javascript reactjs firebase google-cloud-firestore react-hooks
2021-05-08 18:20:20

我目前正在创建待办事项列表中起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 仍会继续检索相同的任务。例如,在加载时初始 todoList 更新为[task1, task2, task3]创建新任务并再次调用快照函数时,我希望 todoList 更新为[task1, task2, task3, task4]. 但是,[task1, task2, task3, task1, task2, task3, task4]每当再次调用快照函数时,我都会返回一些化合物的变体

这个问题似乎只发生在 React 而不是原生 JavaScript(任务被创建和检索得很好,没有任何重复)。我尝试过的一些解决方案是将所有内容都包含在 onEffect 中(如果我没有todoList作为依赖项传递,我相信这给了我第一个问题,如果我这样做了会无限循环)并通过调用快照函数unsubscribe()(这仍然给了我第二个问题)。

1个回答

解决了!我将所有内容都嵌套在没有依赖关系的 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();
}, []);