关于反应中的setState
问题描述:
下面是一个从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));
});
});
});
}
答
您设置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]
});
});
});
});
}
答
尝试设置状态之前克隆数组:
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'将保持对该状态中对象的引用。 –
这是不是等同于'this.setState({messages:[]})',因为它在消息firebase回调被触发之前运行? –
@JanneKlouman看起来像是对的,超出了第二个'ref'范围。 –
有没有办法将所有的消息保存在变量中,然后setState只保存一次? – wo99999