Как в этой ситуации избежать бесконечного цикла useEffect

Я работаю над созданием приложения redux, и мне нужны данные из моей базы данных, чтобы они попали в мое хранилище redux после загрузки определенного компонента. Однако мне нужно, чтобы это происходило каждый раз, когда пользователь добавляет новые данные. В настоящее время я могу либо получить данные для первоначальной загрузки, передав в свой эффект пустой массив зависимостей, но это останавливает обновление данных на основе действий пользователя (вам придется обновить страницу, чтобы эффект снова запустился). Но если я добавлю данные в свой массив зависимостей, это вызовет бесконечный цикл, потому что эффект изменит данные, которые наблюдаются в массиве зависимостей. Ниже представлен текущий поток моего кода.

  1. useEffect отправляет действие из MarkerList компонента.
  2. Действие Redux извлекает данные из Firestore и отправляет действие редуктору.
  3. Редуктор обновляет состояние с помощью полезной нагрузки из Firestore.

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

Я попытался настроить onSnapshot прослушиватель firestore, но это не очень хорошо работает с redux. Я попытался использовать пустой массив зависимостей, как указывалось ранее, который правильно извлекает данные в первый раз, но не обновляет мой пользовательский интерфейс при добавлении новых данных без обновления страницы. Очевидно, что отслеживание маркеров в массиве зависимостей вызывает бесконечный цикл.

Эффект в компоненте

useEffect(() => {
  const loadMarkers = async () => {
    props.loadMarkers();
  };
  loadMarkers();
}, []);

Redux Action

export function loadMarkers() {
  let markers = [];
  return dispatch => {
    getMarkersFromDB().then(snap => {
      snap.forEach(doc => {
        markers.push(doc.data());
      });
      dispatch({
        type: constants.LOAD_MARKERS,
        payload: markers
      });
    });
  };
}

person Chase Thorpe    schedule 03.12.2019    source источник
comment
Что еще вызывает отправку действия loadMarkers? Для меня имеет смысл начинать loadMarkers, когда компонент монтируется, но мне неясно, что еще может сигнализировать о появлении новых маркеров. Вы можете опрашивать и вызывать loadMarkers через интервал, или вам нужен какой-нибудь слушатель, чтобы запускать loadMarkers, когда вы знаете, что есть новый.   -  person azundo    schedule 04.12.2019
comment
В настоящее время кроме этого эффекта ничего не запускает loadMarkers. Пользователи могут добавлять новые маркеры (которые размещаются в пользовательском интерфейсе и сохраняются в БД). Я бы хотел, чтобы новый маркер появлялся в пользовательском интерфейсе, как только пользователь отправляет создание нового маркера. Однако я не могу поместить массив маркеров в качестве зависимости, потому что это запускает бесконечный цикл. Я не уверен, как реализовать слушателя с редукцией   -  person Chase Thorpe    schedule 04.12.2019


Ответы (1)


Думаю, я разобрался. Я был так увлечен попытками выяснить, как заставить эффект обрабатывать все манипуляции с данными, что не подумал просто снова вызвать loadMarkers из функции, которая добавляет маркер в мою базу данных. Компонент CreateMarker является отдельным, поэтому я просто подключил его к redux и передал ему действие loadMarkers. Теперь мой MarkerList по-прежнему загружает исходные данные при монтировании, но всякий раз, когда пользователь создает новый маркер, компоненты CreateMarker также отправляют действие loadMarkers. Сейчас все работает.

Спасибо, Азундо, разговор с тобой заставил меня понять, что я был близорук.

person Chase Thorpe    schedule 03.12.2019
comment
Да, звучит правильно! Собирался предложить это или настроить onSnapshot прослушиватель в componentDidMount, который отправляет LOAD_MARKERS действие для каждого снимка - он будет запускаться один раз при первой настройке и снова при каждом изменении базы данных. Вы можете сделать это, например, в своем корневом компоненте, и тогда вы также будете получать обновления, если кто-то или что-то, кроме текущего пользователя, изменит значение в коллекции маркеров. - person azundo; 04.12.2019