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

Posted

技术标签:

【中文标题】Firestore onSnapshot 通过 onEffect 中的状态附加到数组【英文标题】:Firestore onSnapshot appending to array through state within 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() 调用快照函数(这仍然给了我第二个问题)。

【问题讨论】:

【参考方案1】:

解决了!我将所有内容都嵌套在一个没有依赖关系的 useEffect 中,并设法解决了关于状态未正确更新的第一个要点。我没有使用setTodoList(todoList.concat(newTasks)) 正常设置状态,而是使用setTodoList(currentList => currentList.concat(newTasks)) 在功能上设置状态(关于setState 与useState 异步,异步不是我的专长)。在这里找到答案:https://***.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();
, []);

【讨论】:

以上是关于Firestore onSnapshot 通过 onEffect 中的状态附加到数组的主要内容,如果未能解决你的问题,请参考以下文章

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

firestore onSnapshot 执行两次

Firestore 抛出“onSnapshot() 需要 1 到 4 个参数”

哪个反应钩子与firestore onsnapshot一起使用?

Cloud Firestore 中 get() 和 onSnapshot() 的区别

将firestore onSnapShot与react redux一起使用的正确方法