how to deal with firebase onsnapshot as an object or array?

Viewed 187

im doing orders onsnapshot from firebase but im confused how to deal with it, I get an [] when I log it out but when I logout the type of orders it says object,

I'm trying to add the id of each order and place it inside the array orders along with the existing data but its not working , if I

console.log(orders[0]) I get undefined and if I treat it as an object orders['0'] i also get undefined.

here is the code: im using vuejs mounted

async mounted() {
let id = [];
let orders = [];
await db.collection("orders").onSnapshot(doc => {
  doc.docs.forEach(x => {
    id.push(x.id);
    orders.push(x.data());
  });
});


for (order in orders) {
  let i = 0;
  order.id = id[i];
  i++
}
console.log(orders);

}}

the result of this code is the same orders array without any change at all.

2 Answers

You should check first, returning snap is either object or array. Generally I found it return object. Hence you should do like.

mounted = async () => {
let id = [];
let orders = [];
db.collection("orders").on("value", async snapshot => {
let ordersData = snapshot.val();
if (ordersData !== null) {
    Object.values(ordersData).map(item => {
    orders = [...orders, item.data]; //map according to your data
});
}
console.log("orders===>", orders);
});
};

Data is loaded from Firestore asynchronously. While that is happening, your main code continues to execute, so that the user can continue to use the app.

What this means in practice is that in your code the console.log(orders) is executed before any of the orders.push(x.data()) is ever run.

The solution is pretty simple: any code that needs the data from the database, needs to be inside the callback that is called with the data:

async mounted() {
    let id = [];
    let orders = [];
    db.collection("orders").onSnapshot(doc => {
      doc.docs.forEach(x => {
        id.push(x.id);
        orders.push(x.data());
      });
      for (order in orders) {
        let i = 0;
        order.id = id[i];
        i++
      }
      console.log(orders);
    });
  } 
}

Alternatively, you can use async and await to handle the asynchronicity, but in that case you should use get instead of onSnapshot and not use a callback:

async mounted() {
  let id = [];
  let orders = [];
  const snapshot = await db.collection("orders").get();
  snapshot.docs.forEach(x => {
    id.push(x.id);
    orders.push(x.data());
  });
  for (order in orders) {
    let i = 0;
    order.id = id[i];
    i++
  }
  console.log(orders);
}
Related