1

I am trying to display the data read from my firestore collection, but after getting the data from firestore, I tried using a map function to map & display the data accordingly but it ends up with an error:

TypeError: Cannot read property 'map' of undefined

Which may indicate that my events are in a wrong format for the map function or the events are empty.

Here is my code for more clarification:

const [events, setEvents] = React.useState();
  // const events = [];

  React.useEffect(() => {
    db.collection("Events").get()
    .then(querySnapshot => {
      // const data = querySnapshot.docs.map(doc => doc.data());
      let events = [];
      querySnapshot.forEach(doc =>
        events.push({ ...doc.data() })
      )
      console.log(events);
      setEvents(events);
    });
  });

  return (
    <Grid item sm={4}>
      { events.map(event => (
        <Card className={classes.card}>
          <CardHeader
            avatar={
              loading ? (
                <Skeleton variant="circle" width={40} height={40} />
              ) :
              <Avatar
                alt="Ted talk"
                src={event.eventImgUrl}
              />
            }
 .... // code contiues 

I expect the code to display data for each event accordingly

2 Answers 2

2

Since loading data from Firestore may take a while, the initial value of events is going to be null. From reading this answer, it seems you can pass in the initial value to React.useState(), in which case that line should be:

const [events, setEvents] = React.useState([]);

By initializing with an empty array ([]), the map function will just do nothing until the data is loaded.


Alternatively, you can only show the grid once the data is loaded, and show some sort of "loading..." message until that time. Something like:

if (items) {
  return (
    <Grid item sm={4}>
      { events.map(event => (
        <Card className={classes.card}>
          <CardHeader
            avatar={
              loading ? (
                <Skeleton variant="circle" width={40} height={40} />
              ) :
              <Avatar
                alt="Ted talk"
                src={event.eventImgUrl}
              />
            }
   .... // code continues
}
else {
  return (
    <div>Loading...</div>
  )
}
Sign up to request clarification or add additional context in comments.

Comments

0

I think someone could also try adding async await, worked for me just now, but I'm sure there are many other solutions like the above

 React.useEffect( async () => {
   const snapshot = await db.collection("Events").get()
    if (snapshot.empty) {
    console.log("No Docs found")
    }
      setEvents(
         snapshot.docs.map((doc) => {
         return {
         ...doc.data(),
         documentID: doc.id,
         }
      })
   );
    });
  });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.