Search code examples
javascriptfirebasegoogle-cloud-firestoregeolocation

error: cannot read property 'latitude' of undefined in ionic 4 and firebase


I am trying to build an app with ionic 4 and firebase. There are two types of users: simple users and admins. As an admin, I want to see on map where the users are, but only in a certain area. I was able to display my position on map and to update the marker with watchPosition(). I added some locations in my database for the simple users to see if i can access them and then display them on map. Everything worked well, the markers were displayed on map, but now i got this error: Cannot read property 'latitude' of undefined, but i didn't change anything in my code (where i accessed the locations of users) It's strange because a few days ago it worked well, and it worked on android too. Is this a problem from firebase or from geolocation, anyone have an idea?

This is my code:

 getMarkers() {

let usersLocations =[];
firebase
  .firestore()
  .collection("users")
  .get()
  .then(userProfileSnapshot => {
      userProfileSnapshot.docs.forEach(doc => {
        if (doc.data().isAdmin==false)
        usersLocations.push(doc.data());
      });
  }).then((x) => {
    if(this.isAdmin==true)
    for(let i=0; i<usersLocations.length; i++) {
      let userPosition = new google.maps.LatLng(usersLocations[i].Location.latitude, usersLocations[i].Location.longitude);
      let userMarker = new google.maps.Marker({
        position: userPosition,
        icon: {
          url: "http://maps.google.com/mapfiles/ms/icons/yellow-dot.png"
        },
        map: this.map
      });

  //     if(this.haversine_distance(this.locationMarker, userMarker)>1)
  //       userMarker.setVisible(false);
    }
  });

}


Solution

  • All we can say from the code you shared is that for some value of i, usersLocations[i] does not have a Location property. If you didn't change your code, you'll want to check which document is missing that property.

    Alternatively, you can skip such documents and log their ID by changing the second then to:

    for(let i=0; i<usersLocations.length; i++) {
      if (!usersLocations[i] || !usersLocations[i].Location) {
        console.error("Missing Location data in "+i+": "+JSON.stringify(usersLocations[i]));
        continue; // skip further processing of this user
      }
      let userPosition = new google.maps.LatLng(usersLocations[i].Location.latitude, usersLocations[i].Location.longitude);
      let userMarker = new google.maps.Marker({
        position: userPosition,
        icon: {
          url: "http://maps.google.com/mapfiles/ms/icons/yellow-dot.png"
        },
        map: this.map
      });
    }
    

    A slightly more modern/idiomatic way of accomplishing this is:

    firebase
      .firestore()
      .collection("users")
      .get()
      .then(querySnapshot => {
        // Convert the snapshot to an array of IDs and data
        return querySnapshot.docs.map(doc => { doc.id, ...doc.data() });
      })
      .then(documents => {
        // Remove admins
        return documents.filter(doc => doc.isAdmin==false);
      })
      .then(documents => {
        // Remove and log documents that have no location field
        return documents.filter(doc => {
          if (!doc.Location) {
            console.error(`Document ${doc.id} doesn't have a Location`);
            return false; // remove this document from the array
          }
          return true;
        });
      .then(documents => {
        documents.forEach(doc => {
          let userPosition = new google.maps.LatLng(doc.Location.latitude, doc.Location.longitude);
          let userMarker = new google.maps.Marker({
            position: userPosition,
            icon: {
              url: "http://maps.google.com/mapfiles/ms/icons/yellow-dot.png"
            },
            map: this.map
          });
        });
      });