【问题标题】:Using ReactJS how to subscribe multiple onSnapshot collection changes in Firestore使用 ReactJS 如何在 Firestore 中订阅多个 onSnapshot 集合更改
【发布时间】:2021-01-14 01:31:32
【问题描述】:

如何使用 Reactjs 使用多个“onSnapshot”更改?

有人在 ReactJs 应用程序中使用过多个“onSnapshot”吗?

在此视频中React Firebase CRUD TutorialMaksim Ivanov 展示了我们可以通过返回“onSnapshot”输出来订阅 Firestore 更改,如下所示:

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

就我而言,每个“仪表板”都有带有“devicesId”的“卡片”集合。在另一个集合中,有相对的 devicesId 名称和状态。

我需要在屏幕上显示仪表板、卡片和设备的任何更改。

集合“仪表板” /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"

【问题讨论】:

  • 是要更改dashboards 集合数据还是仅更改后续devices 集合数据?我问的原因是因为您不一定需要列出这两个集合,只需要列出将更改数据的集合。
  • @rafael-lemos 这就是为什么你是伟大的系统工程师 ;-)
  • 我可能会使用这种方法。我只能订阅设备数据的更改,但我可以在不刷新页面的情况下更新仪表板名称、颜色、状态、打开或关闭折叠卡。无论如何,你能提供一个关于只听设备集合的建议吗?首先我必须按仪表板过滤以将它们分组

标签: reactjs google-cloud-firestore


【解决方案1】:

正如我在 cmets 中提到的,如果这是唯一会更改的数据,您可以单独收听 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】:

    迟到总比没有好。 我回到这里解释如何使用 ReactJS 在 Firestore 中订阅多个快照集合更改的解决方案。 我是使用 ReactJS 的新手。这就是为什么它对我来说并不明显。

    我将每个快照分成单独的组件。 ReactJS 正常处理 onChange 事件,并根据每个 ID 更新页面。就我而言,我观察到三个相关集合的变化,包括 Dashboard、Cards、Devices,见下文:

    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/>
      );
    };
    

    设备输入

    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>
        );
    };
    

    而且效果很好:-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多