NodeJs/Firestore/React- Storing Firestore query re

2019-08-20 06:40发布

I have a class called user in which it has all the methods and instnace variables a user class would need. In it, i have a method which is responsible for returning query results to an index.js file. In this index.js file, i was hoping to set the state with the value from the query. But this does not work.

function collectres () {
  var store ='';
  var docRef = db.collection("cities").doc("SF");
  docRef.get()
    .then(function (doc) {
      if (doc.exists) {
        console.log("Document data:", doc.data());
        store = doc.data();// when referenced outside, it doesnt hold anything.
      } else {
        // doc.data() will be undefined in this case
        console.log("No such document!");
      }
    })
    .catch(function (error) {
      console.log("Error getting document:", error);
    });
  return store; // returns nothing and seems to not notice the assignment.
}

The function above was within my user class. When referenced from the index, it would look like this.

Random() {
    let a = '';
    a = user.collectres();
    this.setState({name:a});
    console.log(this.state.name);
}

however this would set the state with the previous value. When looking at the console log, i have noticed, the order of logging starts first with the index.js console.log(this.state.name),however shouldnt my collect res's log's show first. Any help would be appreciated.

1条回答
甜甜的少女心
2楼-- · 2019-08-20 07:16

Data is loaded from Firestore asynchronously. The rest of your code continues to execute while the data is being loaded, and then your then callback is called once the data is there.

It's easiest to see this with a few well-placed log statements:

console.log("Starting to load data");
docRef.get().then(function (doc) {
  console.log("Got data");
});
console.log("Started to load data");

When you run this it prints:

Starting to load data

Started to load data

Got data

This probably isn't the output you expected, but it completely explains the behavior you're seeing. Right now your return store runs before the store = doc.data(), which explains why you're not getting the result you want.


This means that any code that needs the data, needs to be inside the then() callback. So if you move the call to setState() to right after store = doc.data(), it will work:

docRef.get().then(function (doc) {
  if (doc.exists) {
    store = doc.data();
    this.setState({name: store});
  } else {
    // doc.data() will be undefined in this case
    console.log("No such document!");
  }
})

Alternatively, you can return the value from within the then() upwards. In that case you'll need a then() in your calling code too:

function collectres () {
  var docRef = db.collection("cities").doc("SF");
  return docRef.get()
    .then(function (doc) {
      if (doc.exists) {
        return doc.data();
      } else {
        // doc.data() will be undefined in this case
        console.log("No such document!");
      }
    })
    .catch(function (error) {
      console.log("Error getting document:", error);
    });
}

And then call it with:

Random() {
    let a = '';
    user.collectres().then(function(a) {
      this.setState({name:a});
    });
}

Asynchronous APIs are extremely common in modern programming, so I highly recommend reading up on them. For more information, see:

查看更多
登录 后发表回答