构造函数中的变量在渲染前未定义,但在

时间:2019-08-08 06:54:24

标签: javascript reactjs firebase react-native

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

我创建了一个先运行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>

2 个答案:

答案 0 :(得分:1)

只需在.then内使用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
       })
    })
}

答案 1 :(得分:0)

调用firebase是异步操作。因此,第一次渲染将是空数组。您应该在.then中进行setState设置,并且还要为首次渲染设置状态。

您还可以设置loading标志,以便在收到服务器响应后可以显示loader并将其设置为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>