Использование ReactJS как подписаться на несколько изменений коллекции onSnapshot в Firestore

#reactjs #google-cloud-firestore

#reactjs #google-облако-firestore

Вопрос:

Как использовать множественные изменения «onSnapshot» с помощью Reactjs?

Кто-нибудь использовал кратные «onSnapshot» в приложении ReactJS?

В этом видео Максим Иванов показывает, что мы можем подписаться на изменения в firestore, вернув вывод «onSnapshot», например:

 React.useEffect(() => {
return db.collection("dashboars").onSnapshot((snapshot) => {
  snapshot.forEach(doc => {
    dashboardsData.push({ ...doc.data(), id: doc.id });
  });
  setDashboards(dashboardsData);
});
}, []);
  

В моем случае каждая «панель мониторинга» имеет коллекцию «cards» с «devicesId». В другой коллекции есть относительный идентификатор устройства с именем и статусом.

Мне нужно показать любые изменения на панели управления, карте и устройствах на экране.

Коллекция «dashboards» / dashboards/OKtApgxGYeMDst/cards/KgKXJrg9SDvXVC возвращает {devicedId:»esp32_456194″}

 Dashboard name: "DASHBOARD 01"
..Card name: "esp32_AF49AC (dev)"
..Card name: "esp32_455FE8"
..Card name: "esp32_45A134"
..Card name: "esp32_456194"
....DeviceId: "esp32_456194"
  

Коллекция «устройства»

 DevideId: "esp32_456194"
--> name: "ED 01", status: "on"
--> name: "ED 02", status: "off"
--> name: "SD 01", status: "off"
--> name: "SD 02", status: "off"
  

желаемый макет

Комментарии:

1. Будут dashboards ли изменены данные коллекции или только последующие devices данные коллекции? Причина, по которой я спрашиваю, заключается в том, что вам не обязательно указывать обе коллекции, только ту, которая будет изменять данные.

2. @rafael-lemos вот почему ты отличный системный инженер 😉

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

Ответ №1:

Как я упоминал в комментариях, вы можете прослушивать devices только коллекцию, если это единственные данные, которые будут изменены. Поскольку вы упомянули, что у вас нет возможности фильтровать устройства по панели мониторинга, вы можете сделать следующее, чтобы прослушать его и изменить данные в макете панели мониторинга (при условии, что dashboardsData массив не будет очищен):

 db.collection("devices").onSnapshot((snapshot) => {
  snapshot.forEach(doc => {
    // using every() to be able to break the loop without a full iteraction
    dashboardsData.forEach.every(function(element) {
       // not sure this is how you populate but doing it as eg.
       if(element.id == doc.id){
         element.data = doc.data();
         return false 
       }
       else {
         return true
       }
    })
  });
  setDashboards(dashboardsData);
});
  

Ответ №2:

Лучше позже, чем никогда. Я возвращаюсь сюда, чтобы объяснить решение о том, как подписаться на несколько изменений коллекции снимков в Firestore с помощью ReactJS. Я новичок в использовании ReactJS. Вот почему это было для меня не очевидно.

Я разделил каждый снимок на отдельные компоненты. ReactJS нормально обрабатывает событие onChange и обновляет страницу на основе каждого идентификатора. В моем случае я наблюдаю изменения в трех связанных коллекциях, включая панель мониторинга, карты, устройства, см. Ниже:

DashboardInput.js

 import { CardsInput } from "./CardsInput";
export const DashboardInput = () => {
  const classes = useStyles();
  const [dashboards, setDashboards] = React.useState([]);
  React.useEffect(() => {
    const db = app.firestore();
    return db.collection("dashboards").where(...).onSnapshot((snapshot) => {
      const dashboardData = []
      snapshot.forEach(doc => {
        dashboardData.push({ ...doc.data(), id: doc.id })
      }
      );
      setDashboards(dashboardData);
    })
  }, []);
  return (
    <ul>
        {dashboards.map(dashboard => (
                <li key={dashboard.id}><CardsInput dashboardId={dashboard.id} /></li>
        ))}
    <ul/>
  )
};
  

CardsInput.js

 import { DevicesInput } from "./DevicesInput";
export const CardsInput = ({ dashboardId }) => {
  const [cards, setCards] = React.useState([]);
  React.useEffect(() => {
    const db = app.firestore();
    return db.collection("dashboards").doc(dashboardId).collection("cards").onSnapshot((snapshot) => {
      const cardData = []
      snapshot.forEach(doc =>
        cardData.push({ ...doc.data(), id: doc.id })
      );
      setCards(cardData);
    })
  }, [dashboardId]);
  return (
    <ul>
      {cards.map(card => (
              <li key={card.id}><DevicesInput devicesId={card.devices} /><li/>
      ))}
    <ul/>
  );
};
  

DevicesInput

 export const DevicesInput = ({ devicesId }) => {
    const [devices, setDevices] = React.useState([]);
    React.useEffect(() => {
        const db = app.firestore();
        return db.collection("devices")
            .where(...).onSnapshot((snapshot) => {
                const deviceData = []
                snapshot.forEach(doc =>
                    deviceData.push({ ...doc.data(), id: doc.id })
                );
                setDevices(deviceData);
            })
    }, []);
    return (
            <ul>
                {devices.map(device => (
                    <li key={device.id}>{device.value}</li>
                ))}
            </ul>
    );
};
  

И это работает очень хорошо 🙂