React Hook UseEffect в сочетании с Firebase создает бесконечный цикл - PullRequest
0 голосов
/ 13 мая 2019

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

const [lists, setLists] = useState([]);

useEffect(() => {
  const dataArray = [];
  /** handleWidgets */
  listsRef
    .once('value', snap => {
      snap.forEach(function(result) {
        firebase
          .database()
          .ref('lists')
          .child(result.key)
          .on('value', snap => {
            if (snap.val()) dataArray.push(snap.val());
          });
      });
    })
    .then(function() {
      setLists(dataArray);
    });
}, [lists]);

По какой-то причине useEffect всегда выполняется и создает огромную проблему с производительностью.Есть ли лучший способ использовать запросы Firebase с React Hooks, как useEffect?Теперь, если списки изменены или нет, useEffect всегда работает.

1 Ответ

1 голос
/ 13 мая 2019

ОБНОВЛЕНИЕ:

Пара вещей:

1) Ваш useEffect подписывается на lists, который устанавливается в этом useEffect, поэтому он запускает повторный запуск.

2) Вы пытаетесь обновить элемент, а затем повторно получить все данные, включая обновленный элемент. Вам не нужно делать это. Как только вы получите «начальное состояние» из Firebase, все изменения могут произойти с этим списком в пределах состояния. Да, вы позвоните, чтобы сделать добавление / обновление / удаление, но вам не нужно каждый раз звонить, чтобы получать новый список, потому что вы знаете, какую информацию вы изменили, и можете просто обновить свой список состояний, чтобы отразить это в то же время вызывая, чтобы фактически обновить базовые данные, чтобы при выходе из Firebase список отображал список, который был в состоянии.

SO!

Удалите lists из [] в конце, чтобы ваш код работал только при монтировании и выглядел следующим образом:

const [lists, setLists] = useState([]);

useEffect(() => {
  const dataArray = [];
  /** handleWidgets */
  listsRef
    .once('value', snap => {
      snap.forEach(function(result) {
        firebase
          .database()
          .ref('lists')
          .child(result.key)
          .once('value', snap => {
            if (snap.val()) dataArray.push(snap.val());
          });
      });
    })
    .then(function() {
      setLists(dataArray);
    });
}, []); // removed lists from subscription []

Тогда, скажем, в методе add это будет выглядеть примерно так:

addItem = listItem => {
    // make copy of array in state
    const newLists = [...lists];

    // add item to list
    newLists.push(listItem);

    // update list in DB with firebase
    /* firebase call here with new list item */

    // update state lists with new array that has new item
    setLists(newLists)
}

И т. Д. И т. Д. Из методов обновления / удаления. Вы просто будете использовать это значение состояния, даже не вызывая Firebase для обновленного списка, потому что он у вас уже есть.

...