我正在尝试使用react native和firebase构建聊天应用程序界面,并且在更新从我的数据库中提取的数据时遇到问题。我可以将现有数据加载到我正在使用的Flatlist中:
const firebaseApp = firebase.initializeApp(firebaseConfig);
let db = firebaseApp.database();
let ref = db.ref("/room");
componentDidMount() {
ref.on('value', function(snapshot) {
snapshot.forEach(function (childSnapshot){
childData.push(childSnapshot.val());
});
this.setState({
messages: childData
});
messageCount = snapshot.numChildren();
}.bind(this));
}
Flatlist Code:
<KeyboardAvoidingView style={styles.inputContainer}>
<FlatList
data={this.state.messages}
// renderItem={({item}) =><Text>{item.contents}</Text>}
keyExtractor = {item => item.timestamp}
renderItem={({item}) => <Bubble style={{margin: 10}}
color="#FFC800" arrowPosition='right'>{item.contents}</Bubble>}
/>}
/>
<Button onPress={()=>{this.onPressButton()}} title="Send">Click me</Button>
</KeyboardAvoidingView>
这是我在文本输入中添加文本的地方
function addMessage(messageText) {
messageCount++;
firebase.database().ref('room/'+messageCount).set({
contents: messageText,
timestamp: firebase.database.ServerValue.TIMESTAMP
});
}
但每当我尝试发送消息时,它都会正确地添加到数据库中,但平面列表会更新以显示:
前一条消息和新消息多次呈现的位置。将新项目从数据库呈现到平面列表的最佳方法是什么?
答案 0 :(得分:0)
查看您的代码,我无法找到您初始化childData
的位置。
假设您的数据库是正确的,那么在将您的数据库分配到您的州之前,您似乎没有清除childData
this.setState({
messages: childData
});
因此,当您的代码运行此推送childData.push(childSnapshot.val());
时,它会向您的数组添加所有新内容并保留旧内容。
示例:
第一个州:
// snapshot.val() contains ['Hello']
childData = ['Hello']
提交文字:World!
更新状态:
// snapshot.val() contains ['Hello', 'World']
childData = ['Hello', 'Hello', 'World!']
要解决此问题的建议是仅使用新值分配数组,因此您可以执行类似push
childData = snapshot.val()
。
我还建议您使用console.log
调试代码,以便了解snapshot.val()
或childData
或this.state.messages
希望有所帮助
编辑:
再次阅读,可能的问题也可能是因为JS是同步的,所以在setState
完成之前调用forEach
。解决方案可能是使用async/await
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
这样的事情:
ref.on('value', async (snapshot) => {
const childData = await snapshot.map((childSnapshot) => {
childSnapshot.val();
});
this.setState({
messages: childData
});
(...)
仅考虑以上代码作为示例
希望有所帮助