0

I am creating a react website where I am using firebase cloud firestore. This is the code which I am currently using(according to the docs):

async function onTypeSelected(type = "Electronics") {
  var querySnapshot = await getDocs(collection(db, type))
  console.log(querySnapshot)
  querySnapshot.forEach(doc => {
    console.log(doc.data())
  })
}

This code is working perfectly. I am able to see the output in the console:

react_error

However if I use .map() method I am getting an error:

async function onTypeSelected(type = "Electronics") {
  var querySnapshot = await getDocs(collection(db, type))
  console.log(querySnapshot)
  var a = querySnapshot.map(
    (doc) => {
      return <Card data={doc.data()} />
    }
  )

  console.log(a)
}

<Card /> is another component which I created by myself:

function Card(props) {
  return (
    <div className='main__container__card'>
      <img src={props.image} />
      <div style={{ marginTop: 20 }} />
      <hr />
      <div style={{ marginTop: 10 }} />
      <h2>{props.price}</h2>
      <div style={{ marginTop: 10 }} />
      <hr />
      <div style={{ marginTop: 10 }} />
      <div className='main__container__card__btn'>
        <CurrentQuantity />
      </div>
    </div>
  )
}

Error:

react_error

What is the error here?

Please comment if more information is needed.

Aditya Dixit
  • 255
  • 2
  • 12

1 Answers1

2

It looks like getDocs isn't returning an Array, but something array-like that happens to have forEach.

There's a good chance you could destructure it into an array,
Try this:

var a = [...querySnapshot].map((doc) => {
  return <Card data={doc.data()} />
});

Or, as T.J. Crowder suggested, Array.from:

var a = Array.from(querySnapshot, (doc) => {
  return <Card data={doc.data()} />
});
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
  • 1
    Even better chance if you do `Array.from(querySnapshot)` instead. That will handle an iterable (as the spread above does) *and* any array-like. Even better, since `Array.from` has a mapping function built-in, you get one pass: `const a = Array.from(querySnapshot, (doc) => /*...*/);` – T.J. Crowder Jun 22 '22 at 11:45
  • 1
    Cool, I never think of `Array.from`, thanks! – Cerbrus Jun 22 '22 at 11:48
  • 1
    I used to **constantly** forget about its mapping function. :-) – T.J. Crowder Jun 22 '22 at 11:48
  • Might be worth it to point out that, according to the Firebase Documentation, QuerySnapshot has a property called `docs` that retrieves an Array. https://firebase.google.com/docs/reference/js/firestore_.querysnapshot.md#querysnapshot_class – Jose Nuno Jun 22 '22 at 11:52
  • @JoseNuno oh if that’s the case, that deserves a answer – Cerbrus Jun 22 '22 at 11:53
  • @Cerbrus The question got closed so I decided to comment here :) – Jose Nuno Jun 22 '22 at 11:54
  • 1
    Unfortunately, this isn't going to work because a [`QuerySnapshot`](https://stackoverflow.com/q/69713260/5648954) is not iterable nor does it have a `length` property. Using the `.docs` property is the way to get an array as shown in the duplicate link: [Map items of collection snapshot in Firebase Firestore](https://stackoverflow.com/q/46614055) – Nick Parsons Jun 22 '22 at 12:04
  • @Cerbrus, so you are saying that `querySnapshot` has an inbuit method called `forEach()`? – Aditya Dixit Jun 22 '22 at 12:37
  • @T.J.Crowder, @Cerbrus The `Array.from()` and array de-structuring methods aren't working. I am getting an empty array even though my database contains data – Aditya Dixit Jun 22 '22 at 12:45
  • @AdityaDixit - It was worth a try. Sounds like you'll have to fall back on `const a = []; querySnapshot.forEach((doc) => { a.push(); });` – T.J. Crowder Jun 22 '22 at 12:57