0

I want retrieve all post then with each post there is a uid, using this uid i want to retrieve user information

My code is like this but it is not working and state is not changing in then block

getAllPost(){ 
    let allPost = firebase.database().ref("all-post");
    let postAll = [];
    allPost.once("value").then(data => {
      data.forEach(function (childSnapshot) {
        let childData = childSnapshot.val();
        childData.postId = childSnapshot.key;
        let userInfo = firebase.database().ref(`users/${childData.uid}`);
        userInfo.once("value").then(data => {
          childData.userInfo = data;
          postAll.push(childData);        
        })
      })
    }).then(()=>{
      this.setState({ allPost: postAll,loading: false  },);
    }).catch(err => {
      this.setState({ loading: false });
    });
  }
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Raam Meena
  • 29
  • 9

1 Answers1

2

As Josh commented, you're not handling the fact that all your userInfo.once() calls are asynchronous. This means that right now your this.setState({ allPost: postAll,loading: false },) call fires before the postAll.push(childData) happen. You should be able to easily see this by adding some console.log statements.

The solution is to wait until all the loading is finished, by using Promise.all():

let allPost = firebase.database().ref("all-post");
let postAll = [];
allPost.once("value").then(data => {
  let promises = [];
  data.forEach(function (childSnapshot) {
    let childData = childSnapshot.val();
    childData.postId = childSnapshot.key;
    let userInfo = firebase.database().ref(`users/${childData.uid}`);
    promises.push(
      userInfo.once("value").then(data => {
        childData.userInfo = data;
        postAll.push(childData);        
      })
    })
  })
  return Promise.all(promises);
}).then(()=>{
  this.setState({ allPost: postAll,loading: false },);
}).catch(err => {
  this.setState({ loading: false });
});
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807