在setstate之后反应未呈现的本机数据

时间:2019-01-14 22:30:17

标签: reactjs firebase react-native asynchronous google-cloud-firestore

所以我一直在使用Firebase作为我的React Native应用程序中的后端,我试图以这种方式获取数据,但是我什么也没渲染,我的活动指示器熄灭了,但是我发现数据数组是在应用程序屏幕中为空,当我执行console.log时,我可以在控制台中看到数据,但是在应用程序屏幕中没有任何显示,请帮我这已经是我努力的日子了。

export default class Leaderboard extends React.Component{


constructor(props){
    super(props)
    this.state = {
        loading : true,
        data : []
    }
}

componentDidMount(){
    firebase.firestore().collection('rankings').get()
        .then(res => {
            let rankArray = []
            res.forEach(document => {
                rankArray.push(document.data())
            })
            return rankArray;
        }).then(res =>{
            let data = []
            res.forEach(item =>{
                firebase.firestore().doc(item.idUser.path)                    
                .get()
                    .then(doc =>{
                        let dataItem = {}
                        dataItem.id = doc.ref.path
                        dataItem.name = doc.data().fullname
                        dataItem.points = doc.data().points
                        dataItem.lc = 'Oran'
                        data.push(dataItem)
                        dataItem = {}

            })
        })
        return data;
    }).then(res =>this.setState({
        loading : false,
        data : res
    })  ).catch(err => console.log(err))


}


render(){

if(this.state.loading){
        return(
        <View style = {styles.container}>
            <ActivityIndicator size= 'large'></ActivityIndicator>
        </View>
        )
}else{
    console.log(this.state.data)
    return(
        <View>
            <Text>{this.state.data.length}</Text>
            <FlatList
                data={this.state.data}
                 renderItem={({item}) => <Text>{item.fullname}</Text>}
            />

        </View>
    )

}

} }

1 个答案:

答案 0 :(得分:0)

之所以无法正常工作,是因为您尝试在res回调中每次forEach()数组的迭代中执行异步函数调用:

 // This is asynchronous
 firebase.firestore().doc(item.idUser.path).get().then(doc =>{ ... })

请考虑修改您的代码以改为使用Promise.all()方法。这将确保在调用后续res处理程序中的setState()之前,.then()数组中每个文档的每个异步操作均已完成:

.then(res => {
        let rankArray = []
        res.forEach(document => {
            rankArray.push(document.data())
        })
        return rankArray;
})
.then(res => {

  // Use promise all to resolve each aync request, per item in the 
  // res array
  return Promise.all(res.map(item => {

    // Return promise from .get().then(..) for this item of res array.
    return firebase.firestore()
    .doc(item.idUser.path)
    .get()
    .then(doc => {

      let dataItem = {}
      dataItem.id = doc.ref.path
      dataItem.name = doc.data().fullname
      dataItem.points = doc.data().points
      dataItem.lc = 'Oran'

      // Return resolve dataItem to array that is relayed to next .then()
      // handler (ie where you call this.setState())
      return dataItem
    })
  }));
})
.then(res =>this.setState({
    loading : false,
    data : res
}))