Javascript 构造函数中的变量在呈现之前未定义,但在呈现之后可见

Javascript 构造函数中的变量在呈现之前未定义,但在呈现之后可见,javascript,reactjs,firebase,react-native,Javascript,Reactjs,Firebase,React Native,我使用firebase调用一些用户数据,并将其存储在一个数组中。然后,在定义状态时,将“noteData”设置为该数组。但是,构造函数中的console.log(this.state.noteData)返回“Array[]”,返回方法不显示映射组件的序列 我创建了一个按钮,运行this.forceUpdate()和console.log(this.state.noteData),这会使所有组件正确呈现,console.log()会返回数组中它应该返回的所有元素 我尝试使用.bind(this)和

我使用firebase调用一些用户数据,并将其存储在一个数组中。然后,在定义状态时,将“noteData”设置为该数组。但是,构造函数中的console.log(this.state.noteData)返回“Array[]”,返回方法不显示映射组件的序列

我创建了一个按钮,运行this.forceUpdate()和console.log(this.state.noteData),这会使所有组件正确呈现,console.log()会返回数组中它应该返回的所有元素

我尝试使用.bind(this)和componentWillMounth(),但我不知道如何确保在render方法第一次运行之前定义状态

看起来在状态更新之前渲染正在运行,只有在按下按钮后重新渲染才能修复它。此外,加载到此屏幕后,我可以多次按forceUpdate()按钮,直到加载几秒钟后才会发生任何事情。我的猜测是,数据在此期间仍在更新

constructor(props){
super(props);

let returnArr = [];

firebase
  .database()
  .ref('/users/' + firebase.auth().currentUser.uid + '/notes')
  .once('value')
  .then(snapshot => {

    snapshot.forEach(childSnapshot => {
      let item = childSnapshot.val();
      item.key = childSnapshot.key;

      returnArr.push(item);
    })
  })

this.state = {
  fontPreference: firebase.auth().currentUser.fontPref,
  noteData: returnArr
}

console.log(this.state.noteData);
}

 /* * * forceUpdate() button * * */      
 <TouchableOpacity
     onPress={() => {
           this.forceUpdate();
           console.log(this.state.noteData)
     }}>
 ...

 /* * * within return method of render *  * */
 <ScrollView>
      {this.state.noteData.map(note => {
        return <NotePreview
          navigation = {this.props.navigation}
          currNoteImg={note.noteImg}
          currNoteTxt={note.noteTxt}
          noteId={note.key}
        />
      })}
 </ScrollView>
构造函数(道具){
超级(道具);
让returnArr=[];
火基
.数据库()
.ref('/users/'+firebase.auth().currentUser.uid+'/notes'))
.once('值')
。然后(快照=>{
snapshot.forEach(childSnapshot=>{
让item=childSnapshot.val();
item.key=childSnapshot.key;
返回推送(项目);
})
})
此.state={
fontPreference:firebase.auth().currentUser.fontPref,
注数据:returnArr
}
console.log(this.state.noteData);
}
/***强制更新()按钮***/
{
这个.forceUpdate();
console.log(this.state.noteData)
}}>
...
/***在渲染的返回方法内***/
{this.state.noteData.map(note=>{
返回
})}

只需在
中使用setState即可。然后

constructor(props){
    super(props);

    let returnArr = [];
    // declare default state
    this.state = {
       fontPreference: firebase.auth().currentUser.fontPref,
       noteData: []
    }

    firebase
      .database()
      .ref('/users/' + firebase.auth().currentUser.uid + '/notes')
      .once('value')
      .then(snapshot => {

        snapshot.forEach(childSnapshot => {
          let item = childSnapshot.val();
          item.key = childSnapshot.key;

          returnArr.push(item);
        })
        // update state
       this.setState({
          noteData: returnArr
       })
    })
}

调用firebase是异步操作。所以第一次渲染时它将是空数组。您应该先在中设置状态,然后再为第一次渲染设置状态

您还可以设置加载标志,以便在收到服务器的响应后显示加载程序并使其为false

constructor(props){
super(props);

let returnArr = [];

firebase
  .database()
  .ref('/users/' + firebase.auth().currentUser.uid + '/notes')
  .once('value')
  .then(snapshot => {

    snapshot.forEach(childSnapshot => {
      let item = childSnapshot.val();
      item.key = childSnapshot.key;

      returnArr.push(item);

      this.setState({noteData: returnArr});
    })
  })

this.state = {
  fontPreference: firebase.auth().currentUser.fontPref,
  noteData: returnArr
}

console.log(this.state.noteData);
}

 /* * * forceUpdate() button * * */      
 <TouchableOpacity
     onPress={() => {
           this.forceUpdate();
           console.log(this.state.noteData)
     }}>
 ...

 /* * * within return method of render *  * */
 <ScrollView>
      {this.state.noteData.map(note => {
        return <NotePreview
          navigation = {this.props.navigation}
          currNoteImg={note.noteImg}
          currNoteTxt={note.noteTxt}
          noteId={note.key}
        />
      })}
 </ScrollView>
构造函数(道具){
超级(道具);
让returnArr=[];
火基
.数据库()
.ref('/users/'+firebase.auth().currentUser.uid+'/notes'))
.once('值')
。然后(快照=>{
snapshot.forEach(childSnapshot=>{
让item=childSnapshot.val();
item.key=childSnapshot.key;
返回推送(项目);
this.setState({noteData:returnArr});
})
})
此.state={
fontPreference:firebase.auth().currentUser.fontPref,
注数据:returnArr
}
console.log(this.state.noteData);
}
/***强制更新()按钮***/
{
这个.forceUpdate();
console.log(this.state.noteData)
}}>
...
/***在渲染的返回方法内***/
{this.state.noteData.map(note=>{
返回
})}

注意我们应该使用set state callback立即查看更改,因为setState()是aync,setState()之后的控制台将不会显示数据。将控制台放在setState回调中,如`this.setState({blah:blah},()=>console.log(this.state.blah))`您应该将this.state移到承诺的下方,以便在承诺执行时,该状态不是未定义的。使用then块中的setState推送新数据。