Search code examples
firebasereact-nativegeofire

Trying to get firebase values out of Promise


I am new to react native and I am having hard times getting values out of a firebase query inside a promise.

I tried to setState in the promise but the console returns : TypeError: _this2.setState is not a function.

_getActivites() {
      const latitude = 42.297761;
      const longitude = 4.636235;
      const radius = 5;

  var keys = [];
  var activitesToState = [];

  const firebaseRef = firebase.database().ref("activites_locations/");
  const geoFire = new GeoFire(firebaseRef);
  var geoQuery;
  var activites = [];

  geoQuery = geoFire.query({
    center: [latitude, longitude],
    radius: radius
  });

  geoQuery.on("key_entered", function(key, location, distance) {
    keys.push(key);
  });

  geoQuery.on("ready", function() {
    var promises = keys.map(function(key) {
      return firebaseRef.child(key).once("value");
    });
    Promise.all(promises).then((snapshots) => {
      snapshots.forEach(function(snapshot) {
        activites.push(snapshot.val());
      });
      this.setState({
        activitesState: activites,
      })
    }).catch((error) => {
      console.log(error);
    });

  });

};

componentDidMount() {
  firebase.auth().signInAnonymously()
    .then(() => {
      this.setState({
        isAuthenticated: true,
      });
  });

  this._getActivites();
}

Solution

  • You are losing the value of this in your function calls. You should bind your calls by updating your functions to arrow functions. You can also stop prevent the lost of this by setting it as a variable in the scope of your function.

    Refactoring your code you could have something like this:

    _getActivites = () => { // change to arrow function
      const that = this;  // capture the value of this
      const latitude = 42.297761;
      const longitude = 4.636235;
      const radius = 5;
    
      var keys = [];
      var activitesToState = [];
    
      const firebaseRef = firebase.database().ref('activites_locations/');
      const geoFire = new GeoFire(firebaseRef);
      var geoQuery;
      var activites = [];
    
      geoQuery = geoFire.query({
        center: [latitude, longitude],
        radius: radius
      });
    
      geoQuery.on('key_entered', (key, location, distance) => { // change to arrow function
        keys.push(key);
      });
    
      geoQuery.on('ready', () => { // change to arrow function
        var promises = keys.map((key) => { // change to arrow function
          return firebaseRef.child(key).once('value');
        });
        Promise.all(promises).then((snapshots) => {
          snapshots.forEach((snapshot) => {
            activites.push(snapshot.val());
          });
          that.setState({ activitesState: activites }); // use "that" instead of "this"
        }).catch((error) => {
          console.log(error);
        });
      });
    }
    

    Here is a great article about this and it losing its context.