Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React + Firestore : Return a variable from a query

I'm learning React and Firestore currently and am a bit stuck. I'm trying to retrieve a users name from a firestore collection by searching their uid.

The following code is executed in a map of 'lessons' to create a list.

{lesson.post_author && findName(lesson.post_author)}

The following code is the findName function.

let findName = uid => {
    firebase.firestore().collection("users")
      .where('uid', '==', uid)
      .get()
      .then(querySnapshot => {
          console.log(querySnapshot.docs[0].data().name);
    });

  };

Currently, the findName function will console log all of the names to the console successfully. I've altered the code to be able to console log outside of the firestore call, but that returns a promise pending in console.

The goal of the code is to return the name rather then the uid in the list.

Any help would be much appreciated. Thank you!

like image 369
Timothy Lentz Avatar asked Oct 28 '25 11:10

Timothy Lentz


1 Answers

As others have explained, you can't return that value, since it's loaded from Firestore asynchronously. By the time your return runs, the data hasn't loaded yet.

In React you handle this by putting the data in the component's state, and using it from there. If you do this, your render method can simply pick it up from the state, with something like:

{lesson.post_author && findName(lesson.post_author_name)}

(the above assumes that lesson indirectly comes from the state.

It's a bit easier if we pretend there's only one lesson, and you have these values straight in the state:

{state.post_author && findName(state.post_author_name)}

Now I'll assume you already have the post_author and you just need to look up the author's name. That means that somewhere in/after componentDidMount you'll load the additional data and add it to the state:

componentDidMount() {
  firebase.firestore().collection("users")
    .where('uid', '==', this.state.uid)
    .get()
    .then(querySnapshot => {
      this.setState({ post_user_name: querySnapshot.docs[0].data().name });
  });
}

Now the loading of the data still happens asynchronously, so the call to setState() happens some time after componentDidMount has completed. But React is aware that changing the state may require a refresh of the component, so it responds to the call to setState() by rerendering it.

Note that I'd highly recommend using each user's UID as the ID of the documents in users. That way you don't need a query and can just do a directly lookup:

componentDidMount() {
  firebase.firestore().collection("users")
    .doc(this.state.uid)
    .get()
    .then(doc => {
      this.setState({ post_user_name: doc.data().name });
  });
}
like image 178
Frank van Puffelen Avatar answered Oct 30 '25 01:10

Frank van Puffelen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!