Reactjs 关于在React中设置状态

Reactjs 关于在React中设置状态,reactjs,react-native,Reactjs,React Native,下面是一个从firebase数据库获取消息的函数,但它仅将状态设置为一条消息 但是,console.log可以在对象中记录多条消息。 我的功能有什么问题吗 getMessages(){ var messages = []; firebaseApp.database().ref('users/'+firebase.auth().currentUser.uid+'/userChat/'+firebase.auth().currentUser.uid).orderByValue().limitToLa

下面是一个从firebase数据库获取消息的函数,但它仅将状态设置为一条消息

但是,
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));
    });
  });
});
}
您正在
forEach
块内设置状态。尝试将其移出迭代块

正如JanneKlouman提到的,在进行异步调用时,将其从iterration块中删除还不够好。 您可以创建一个新数组并将其设置为每次迭代时的状态,react将批处理这些设置状态调用:

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]
        });
      });
    });
  });
}

请在设置状态之前尝试克隆阵列:

getMessages(){
让消息=[];
firebaseApp.database().ref('users/'+firebase.auth().currentUser.uid+'/userChat/'+firebase.auth().currentUser.uid).orderByValue().limitToLast(10).once('value',(dataSnapshot)=>{
dataSnapshot.forEach((子项)=>{
firebaseApp.database().ref('messages').child(child.key).once('value',(message)=>{
常量消息={
_id:Math.round(Math.random()*1000000),
text:message.val().text,
createdAt:新日期(message.val().timestamp),
用户:{
_id:1,
名称:“开发者”,
},
};
//克隆消息
消息=[…消息,消息];
this.setState({messages});
});
});
});
}

这不等于
this.setState({messages:[]})
,因为它是在firebase回调消息被激发之前运行的吗?@JanneKlouman看起来你是对的,它超出了第二个
ref
范围。有没有办法先将所有消息保存在一个变量中,然后只设置一次state?
spread
操作符只在一个层次深度上工作,这意味着
meesage。用户
会将对对象的引用保持在该状态。