1

I have a few nested called when using Firestore. With these, they rely on the use of the .then() because they are network calls. They appear to be so nested that they stop having access to the list that I am looking to update called "messages."

Because of this mess, I am updating state every iteration of the loop which is wildly non performant.

How can I push to the messages array given this as a starting point?:

BTW, this method onCollectionUpdate is bound in my constructor like this.onCollectionUpdate = this.onCollectionUpdate.bind(this). Thank you!

onCollectionUpdate = querySnapshot => {
    const messages = [];
    querySnapshot.forEach(doc => {
      const { _id, text, createdAt, user } = doc.data();
      var userId = user.id
      var userRef = firebase.firestore().collection('users').doc(userId)
      userRef.get().then(data => {
        var user = data.data()
        var userObject = {
            _id: userId,
            name: user.name,
            avatar: user.profilePictureURL
        }
        var newMessage = {
          _id,
          text,
          createdAt: new Date(createdAt.seconds),
          user: userObject
        }
        this.setState(prevState => ({messages: [...prevState.messages,newMessage]}))

        messages.push() //Not working. By time it reaches set state below (outside of the loops) it is empty.
      })
    })
    this.setState({
      messages,
      loading: false,
    });
  }

1 Answer 1

2

Here's a solution

onCollectionUpdate = querySnapshot => {
    var promises = [];
    const messages = [];

    querySnapshot.forEach(doc => {
      const { _id, text, createdAt, user } = doc.data();
      var userId = user.id
      var userRef = firebase.firestore().collection('users').doc(userId)
      promises.push(
        userRef.get()
        .then(data => {
          var user = data.data()
          var userObject = {
            _id: userId,
            name: user.name,
            avatar: user.profilePictureURL
          }
          return {
            _id,
            text,
            createdAt: new Date(createdAt.seconds),
            user: userObject
          }
        })
      )
    })

    Promise.all(promises).then(newMessages=> {
        this.setState(prevState => {
            return {
                messages: [...prevState.messages, ...newMessages],
                loading: false,
              }
        })
    })
  }

Once all you get all the responses, you call setState once. Hope this is what you wanted :)

Sign up to request clarification or add additional context in comments.

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.