Правильное обновление состояния после извлечения данных из firestore

Я пытаюсь использовать Firestore Snapchats для получения изменений в базе данных в реальном времени. Я использую react-native-cli: 2.0.1 и react-native: 0.64.1 .

export const WelcomeScreen = observer(function WelcomeScreen() {
    const [listData, setListData] = useState([]);
    
    const onResult = (querySnapshot) => {
       const items =  []
       firestore()
       .collection("Test")
       .get()
       .then((querySnapshot) => {
           querySnapshot.forEach(function(doc) {
             const tempData = {key: doc.id, data: doc.data}
              items.push(tempData);
           });
           setListData(items)
        });
      }
      
      const onError = (error) => {
        console.error(error);
      }
      
      firestore().collection('Test').onSnapshot(onResult, onError);

}

Все работает отлично, пока я не использую setListData для обновления списка данных. Приложение больше не отвечает, и я получаю предупреждающее сообщение каждый раз, когда пытаюсь добавить или удалить данные из базы данных.

Please report: Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code

Я создаю тупик, устанавливая состояние таким образом?

можно ли использовать useState вне функционального компонента

Dharmik Patel 22.03.2022 11:40
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
1
30
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, вы не хотите настраивать прослушиватель моментальных снимков в теле вашего компонента. Это приводит к увеличению числа слушателей, потому что каждый раз, когда вы выполняете рендеринг, вы добавляете новый слушатель, но каждый слушатель приводит к повторному рендерингу и т. д. Поэтому настройте слушатель только один раз в useEffect:

const [listData, setListData] = useState([]);

useEffect(() => {
  function onResult(querySnapshot) {
    // ...
  }
  function onError(error) {
    console.info(error);
  }

  const unsubscribe = firestore().collection('Test').onSnapshot(onResult, onError);
  return unsubscribe;
}, []);

Кроме того, ваша функция onResult будет вызываться, когда вы получите результат, и все же вы заставляете ее развернуться и немедленно выполнить get, чтобы повторно запросить данные, которые у нее уже есть. Вместо этого просто используйте предоставленный вам снимок:

function onResult(querySnapshot) {
  const items = []
  querySnapshot.forEach(function(doc) {
    const tempData = {key: doc.id, data: doc.data()}
    items.push(tempData);
  });
  setListData(items);
}

Спасибо, это сработало отлично. Только один вопрос, где возвращается «отписаться»? Где я могу его использовать?

user567 22.03.2022 20:43

onSnapshot возвращает функцию отмены подписки, которая отключит прослушиватель моментальных снимков. Затем я возвращаю его из useEffect. Когда вы возвращаете функцию из useEffect, это сообщает react, какую логику очистки требует эффект. React вызовет отмену подписки, когда компонент отключится (или когда эффект запустится снова, но этого не произойдет для этого эффекта).

Nicholas Tower 22.03.2022 22:56

Другие вопросы по теме