Как правильно обновить состояние с помощью Firebase и использоватьEffect ()? - PullRequest
0 голосов
/ 05 ноября 2019

Я пытаюсь получить данные из Firebase и затем отправить их в свое состояние. Цель состоит в том, чтобы создать механизм, который будет делать это каждый раз, когда данные в Firebase меняются.

Я использовал on() метод вместе с useEffect(). К сожалению, React не выполняет повторную визуализацию моего компонента, даже когда состояние изменяется. (игнорируйте прямую ссылку, это только для тестирования)

const [tasks, setTasks] = useState([]);

    useEffect(() => {
        const fetchedTasks = [];
        const ref = props.firebase.db.ref('users/1zfRCHmD4MVjJj7L884LL4TMwAH3');
        const listener = ref.on('value', snapshot => {
            snapshot.forEach(childSnapshot => {
                const key = childSnapshot.key;
                const data = childSnapshot.val();
                fetchedTasks.push({ id: key, ...data });
            });
            setTasks(fetchedTasks);
        });
        return () => ref.off('value', listener);
    }, []);

На этом этапе, когда я вручную изменяю свои данные в Firebase Console, я вижу в своих инструментах разработчика, что запускает прослушиватель, данные выбираются,но он сливается с предыдущим состоянием (задачами).

Я хочу заменить предыдущее состояние, конечно. Во-вторых, компонент не повторный рендеринг. Я знаю, что за это отвечает пустой список зависимостей («[]»), и компонент монтируется только один раз, но когда я удаляю список, компонент обновляется и быстро замораживает мой браузер. Я также попробовал "[tasks]", и результат был похож - компонент рендерит снова и снова. Firebase предоставляется контекстом, и ESLint отображает это:

"React Hook useEffect отсутствует зависимость: 'props.firebase.db'. Включите его или удалите массив зависимостей."

Когда я это делаю, он все еще не работает и компонент не обновляется.

1 Ответ

0 голосов
/ 05 ноября 2019

Поскольку мой комментарий решил эту проблему, вот официальный ответ:

Причина, по которой ваше состояние всегда объединяется, состоит в том, что ваша переменная fetchedTasks объявляется только один раз, когда ловушка useEffect запускается onMount. После этого каждый раз, когда ваша база данных firebase обновляет новые значения и вы вызываете fetchedTasks.push(...), вы нажимаете на один и тот же «старый» массив. Поэтому ваш список становится все длиннее и длиннее.

Одним из решений было бы просто повторно объявить fetchedTasks или установить его обратно в пустой массив.

const [tasks, setTasks] = useState([]);

    useEffect(() => {
        const ref = props.firebase.db.ref('users/1zfRCHmD4MVjJj7L884LL4TMwAH3');
        const listener = ref.on('value', snapshot => {
            const fetchedTasks = [];
            snapshot.forEach(childSnapshot => {
                const key = childSnapshot.key;
                const data = childSnapshot.val();
                fetchedTasks.push({ id: key, ...data });
            });
            setTasks(fetchedTasks);
        });
        return () => ref.off('value', listener);
    }, [props.firebase.db]);

Другим было бывместо этого использовать .map и использовать возвращаемое значение для setTasks. Я думаю, что это было бы моим предпочтением:

const [tasks, setTasks] = useState([]);

    useEffect(() => {
        const ref = props.firebase.db.ref('users/1zfRCHmD4MVjJj7L884LL4TMwAH3');
        const listener = ref.on('value', snapshot => {
            const fetchedTasks = snapshot.map(childSnapshot => {
                const key = childSnapshot.key;
                const data = childSnapshot.val();
                return { id: key, ...data };
            });
            setTasks(fetchedTasks);
        });
        return () => ref.off('value', listener);
    }, [props.firebase.db]);

, также обратите внимание, что вам нужно будет передать props.firebase.db в ваш массив зависимостей, чтобы избавиться от предупреждения eslint. Ссылка на props.firebase.db никогда не должна изменяться, поэтому ее следует сохранить, чтобы объявить ее в массиве зависимостей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...