每当添加新数据时,FlatList 都会多次重新呈现来自 Firebase 的数据
FlatList rerenders data from Firebase multiple times whenever new data is added
我正在尝试使用本机反应和 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代码:
<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
});
}
该代码给出了我想要的以下结果(忽略糟糕的样式):
但是每当我尝试发送消息时,它都会正确地添加到数据库中,但是平面列表会更新以显示:
其中多次呈现上一条消息和新消息。将数据库中的新项目呈现到平面列表中的最佳方法是什么?
查看你的代码我找不到你在哪里初始化你的 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
[=28 正在检索的内容=]
希望对您有所帮助
编辑:
再次阅读,一个可能的问题也可能是因为 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
});
(...)
以上代码为例
希望对您有所帮助
我正在尝试使用本机反应和 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代码:
<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
});
}
该代码给出了我想要的以下结果(忽略糟糕的样式):
但是每当我尝试发送消息时,它都会正确地添加到数据库中,但是平面列表会更新以显示:
其中多次呈现上一条消息和新消息。将数据库中的新项目呈现到平面列表中的最佳方法是什么?
查看你的代码我找不到你在哪里初始化你的 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
[=28 正在检索的内容=]
希望对您有所帮助
编辑:
再次阅读,一个可能的问题也可能是因为 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
});
(...)
以上代码为例
希望对您有所帮助