【问题标题】:How do I ensure setState is called after the Firebase query populates array?如何确保在 Firebase 查询填充数组后调用 setState?
【发布时间】:2017-01-20 14:24:36
【问题描述】:

我是 Firebase 的新手,并且将它与 React Native 一起使用。我正在尝试使用 Firebase 中的数据填充 ListView。我看到我现在可以在 Firebase 中使用 Promises,但是,我似乎无法将它们与 .on() 一起使用,而只能与 .once 一起使用。因为需要监听变化,所以需要使用.on()

当我想确保在从 Firebase 检索数据之后(且仅在之后)设置状态时,我面临的挑战就来了。我的代码如下:

listen() {
    var self = this
    var currentUserID = firebase.auth().currentUser.uid
    var postList = firebase.database().ref('/users/'+currentUserID+'/postKeys')
    postList.on('value', function(snapshot) {
      var posts = []
      snapshot.forEach((child)=> {
        var postID = child.val().postID
        var postRef = firebase.database().ref('posts/'+postID)
        postRef.orderByChild('sortedDateInMilliseconds').on('value', function(postSnap) {
          posts.push(postSnap.val())          
        })

      })
      self.setState({
        postCount:posts.length,
        dataSource:self.state.dataSource.cloneWithRows(posts)
      })
    })
  }

结果是我最初得到一个空视图,因为在查询填充帖子数组之前调用了render()。有谁知道如何确保在查询填充数组后调用self.setState({})

非常感谢您的帮助。

【问题讨论】:

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


    【解决方案1】:

    我不完全确定用空数组调用是什么意思。我能想象的唯一原因是,如果您最初在该位置还没有数据时被调用。如果是这个原因,您可以使用snapshot.exists() 检测它:

    listen() {
        var self = this
        var currentUserID = firebase.auth().currentUser.uid
        var postList = firebase.database().ref('/users/'+currentUserID+'/postKeys')
        postList.on('value', function(snapshot) {
          if (snapshot.exists()) {
            var posts = []
            snapshot.forEach((child)=> {
              var postID = child.val().postID
              var postRef = firebase.database().ref('posts/'+postID)
              postRef.orderByChild('sortedDateInMilliseconds').on('value', function(postSnap) {
                posts.push(postSnap.val())          
              })
    
            })
            self.setState({
              postCount:posts.length,
              dataSource:self.state.dataSource.cloneWithRows(posts)
            })
          }
        })
      }
    

    如果这不能解决问题,你可以设置一个 jsbin 来重现它吗?

    【讨论】:

    • 先生,您是一位绅士和一位学者。非常感谢你的帮助。非常有意义并且有效。我很感激。
    【解决方案2】:

    你可以使用setTimeout函数作为

    setTimeOut(try,3000); 
    function try(){
    self.setState({
            postCount:posts.length,
            dataSource:self.state.dataSource.cloneWithRows(posts)
          });
    }
    

    现在self.setState({})如果不将3000更改为5000,将在查询后调用

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-03
      • 2021-02-03
      • 2018-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-02
      • 1970-01-01
      相关资源
      最近更新 更多