2017-10-07 67 views
1

下面是一個從firebase數據庫獲取消息的函數,但它只有setState只有一個消息。關於反應中的setState

但是,console.log可以記錄對象中的多個消息。 我的功能有什麼問題嗎?

getMessages(){ 
var messages = []; 
firebaseApp.database().ref('users/'+firebase.auth().currentUser.uid+'/userChat/'+firebase.auth().currentUser.uid).orderByValue().limitToLast(10).once('value', (dataSnapshot) => { 
    //alert(JSON.stringify(dataSnapshot.val())); 
    dataSnapshot.forEach((child) => { 
    firebaseApp.database().ref('messages').child(child.key).once("value", (message)=>{ 
     //alert(JSON.stringify(messages)); 
     messages.push({ 
     _id: Math.round(Math.random() * 1000000), 
     text: message.val().text, 
     createdAt: new Date(message.val().timestamp), 
     user: { 
      _id: 1, 
      name: 'Developer', 
     }, 
     }); 
     this.setState({ 
     messages: messages 
     }); 
     console.log('woooo'+JSON.stringify(messages)); 
    }); 
    }); 
}); 
} 

回答

1

您設置forEach塊內的狀態。嘗試在迭代塊外移動它

正如JanneKlouman所說的,當您在進行異步調用時,將它從iterration塊中移除並不夠好。 您可以創建一個新的數組,並將其設置在每個迭代狀態,反應器會批量的設置狀態的呼叫:

function getMessages() { 
    var messages = []; 
    firebaseApp.database().ref('users/' + firebase.auth().currentUser.uid + '/userChat/' + firebase.auth().currentUser.uid).orderByValue().limitToLast(10).once('value', (dataSnapshot) => { 
    //alert(JSON.stringify(dataSnapshot.val())); 
    dataSnapshot.forEach((child) => { 
     firebaseApp.database().ref('messages').child(child.key).once("value", (message) => { 
     const newMessage = { 
      _id: Math.round(Math.random() * 1000000), 
      text: message.val().text, 
      createdAt: new Date(message.val().timestamp), 
      user: { 
      _id: 1, 
      name: 'Developer', 
      }, 
     } 
     const nextState = this.state.messages.map(message => { 
      return { 
      ...message, 
      user: {...meesage.user} // i think we must do this in order to break out of the reference as spreading will only work on a shallow level 
      } 
     }); 
     this.setState({ 
      messages: [...nextState, newMessage] 
     }); 
     }); 
    }); 
    }); 
} 
+0

這是不是等同於'this.setState({messages:[]})',因爲它在消息firebase回調被觸發之前運行? –

+0

@JanneKlouman看起來像是對的,超出了第二個'ref'範圍。 –

+0

有沒有辦法將所有的消息保存在變量中,然後setState只保存一次? – wo99999

0

嘗試設置狀態之前克隆數組:

getMessages(){ 
    let messages = []; 
    firebaseApp.database().ref('users/'+firebase.auth().currentUser.uid+'/userChat/'+firebase.auth().currentUser.uid).orderByValue().limitToLast(10).once('value', (dataSnapshot) => { 
    dataSnapshot.forEach((child) => { 
     firebaseApp.database().ref('messages').child(child.key).once("value", (message)=>{ 
     const message = { 
      _id: Math.round(Math.random() * 1000000), 
      text: message.val().text, 
      createdAt: new Date(message.val().timestamp), 
      user: { 
      _id: 1, 
      name: 'Developer', 
      }, 
     }; 

     // Clone messages 
     messages = [...messages, message]; 

     this.setState({ messages }); 
     }); 
    }); 
    }); 
} 
+0

'spread'運算符只能在一個層次上工作,這意味着'meesage.user'將保持對該狀態中對象的引用。 –