toshi
toshi

Reputation: 2814

React doesn't render array value from firebase and array's length is 0 despite having the value on console

I am trying to fetch the data from firebase and push the data to the array one by one in a loop. But array of the fetched data doesn't show up on the React component.

I console logged and I found that as the picture below strangely shows, console.log(array.length) is 0, but console.log(array.length) show the contents of array.

enter image description here

code is as follows.

 const getThread = (threadID) => {
  return db.ref(`threads/${threadID}`).once('value')
  .then((snapshot)=>{
    return snapshot.val()
  })
}

const getThreadList = (id) => {
  let threadList = []
  return db.ref(`users/${id}/friends`).once('value')
  .then((snapshot)=>{
    let friends = snapshot.val()
    for(let key in friends){
      if(friends.hasOwnProperty(key)) {
        getThread(friends[key].threadID)
        .then((thread)=>{
          threadList.push(thread)
        })
      }
    }
    return threadList
  })
}

class SomeComponent extends Component{

  componentDidMount(){
    let { id } = this.props
    getThreadList(id)
    .then(threadList => {
      this.setState(() => ({ threadList }))
    })
  }

  render(){

    //value of threadList doses't appear

I suspect this is due to the misuse of Promise so console.log shows value but React component doesn't show anything. But I also suspect the React side and couldn't locate exactly where the problem is.

It would be much appreciated if you suggest any clue on this problem.

Upvotes: 0

Views: 93

Answers (1)

Yury Tarabanko
Yury Tarabanko

Reputation: 45106

You are not waiting for the nested promises to resolve. You could use Promise.all to accomplish the task.

const getThreadList = (id) => {
  return db.ref(`users/${id}/friends`).once('value')
  .then((snapshot)=>{
    let friends = snapshot.val()
    const threads = []
    for(let key in friends){
      if(friends.hasOwnProperty(key)) {
        threads.push(getThread(friends[key].threadID))
      }
    }
    return Promise.all(threads)
  })
}

Or using Object.values

const getThreadList = id => {
  return db
    .ref(`users/${id}/friends`)
    .once("value")
    .then(snapshot => {
      const loadingThreads = Object.values(snapshot.val()).map(friend =>
        getThread(friend.threadID)
      );
      return Promise.all(loadingThreads);
    });
};

Upvotes: 2

Related Questions