#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>
);
};
И это работает очень хорошо 🙂