React native和Firebase承诺 - 渲染

时间:2017-06-13 11:36:28

标签: javascript firebase react-native firebase-realtime-database setstate

我在我的代码中使用了两个链式firebase请求。第一个是获取所有评论,然后我迭代所有结果,为循环中的每个元素发出第二个firebase请求。

在循环之后,我使用state使用新数据更新了setState。而且这个更新使我的GUI变得透明,如下所示:

enter image description here

底部每次都是随机透明的,有时渲染可见一点,有时根本不可见。当我删除setState块时,一切都很好。

有问题的代码:

    getReviews() {
      let reviewData = {}
      let vendorId = this.props.item.vendor_id
      let product = this.props.item.key

      firebase.database().ref('u_products/' + vendorId + '/' + product + '/reviews/').once('value', (data) => {
        reviewData = data.val()
        if (!reviewData) {
          this.setState({
            loadedReviews: true
          })
          return
        } else {
          for (var key in reviewData) {
            firebase.database().ref('users/' + reviewData[key].poster_uid + '/').once('value', (data) => {
              let userData = data.val()
              if (userData) {
                this.getUserImageUrl()
                 ...
              }
            })
          }
          this.state.reviewData = reviewData
            this.setState({
              dataSource: this.state.dataSource.cloneWithRows(reviewData),
              loadedReviews: true,
            })
        }
      })
    }

预期行为是第一个firebase请求 - >第二个迭代第一个请求的所有结果 - > setState。

还有其他人有这个问题吗?

1 个答案:

答案 0 :(得分:1)

firebase' .once()返回Promise,因此您需要创建一个Promise数组,然后调用Promise.all(array).then((arrayOfData) => { ... });

您现在可以处理生成的数组,然后调用.setState()

这是一个模型:



/* firebase mockup */
function Result(url) {
  this.url = url;
  this.once = function(param, callback) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        var data = {
          val: () => {
            return this.url + " query result";
          }
        };
        resolve(data);
      }, Math.random() * 500 + 1000);
    });
  };
}
var firebase = {
  database: function() {
    return firebase;
  },
  ref: function(url) {
    return new Result(url);
  }
};

var reviewData = {
  "test": {
    poster_uid: "testData"
  },
  "2nd": {
    poster_uid: "2ndData"
  }
};

// ACTUAL IMPORTANT CODE BELOW #################

var arrayOfPromises = [];
for (var key in reviewData) {
  arrayOfPromises.push(firebase.database().ref('users/' + reviewData[key].poster_uid + '/').once('value'));
}
Promise.all(arrayOfPromises).then(function(arrayOfResults) {
  arrayOfResults.map((data, i) => {
    let userData = data.val();
    if (userData) {
      console.log(i, userData);
    }
  });
  console.log("setting state now");
});