【问题标题】:Firestore onSnapshot appending to array through state within onEffectFirestore onSnapshot 通过 onEffect 中的状态附加到数组
【发布时间】:2020-09-13 16:18:04
【问题描述】:

我目前正在 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() 调用快照函数(这仍然给了我第二个问题)。

【问题讨论】:

    标签: javascript reactjs firebase google-cloud-firestore react-hooks


    【解决方案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();
    }, []);
    

    【讨论】:

      猜你喜欢
      • 2020-06-05
      • 2018-06-13
      • 2020-12-17
      • 2021-07-04
      • 1970-01-01
      • 2020-02-25
      • 1970-01-01
      • 1970-01-01
      • 2019-10-12
      相关资源
      最近更新 更多