Firestore onSnapshot добавляется к массиву через состояние внутри onEffect - PullRequest
1 голос
/ 26 мая 2020

В настоящее время я создаю список дел в 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
});

Есть несколько проблем, которые всплывают, когда я пробую разные варианты этого (нажатие на пустой массив, а затем объединение двух массивов вместе и т. Д. c.):

  • Состояние списка задач не сохраняется на новом снимке. Например, создание новой задачи 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 в качестве зависимости, и если бы я сделал, то бесконечно l oop) и вызов функции моментального снимка через unsubscribe() (что все еще дало мне вторую проблему).

1 Ответ

0 голосов
/ 27 мая 2020

Решено! Я вложил все в useEffect без каких-либо зависимостей, и мне удалось разрешить первый пункт, касающийся некорректного обновления состояний. Вместо того, чтобы устанавливать состояние, как обычно, используя setTodoList(todoList.concat(newTasks)), я функционально устанавливаю состояние, используя setTodoList(currentList => currentList.concat(newTasks)) (что-то об асинхронности setState относительно useState, asyn c не является моей спецификой). Найдите ответ здесь: { ссылка }.

Вот последний код обновления снимка (я как-то решил, что 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();
}, []);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...