【问题标题】:FlatList rerenders data from Firebase multiple times whenever new data is added每当添加新数据时,FlatList 都会多次重新渲染 Firebase 中的数据
【发布时间】:2018-05-21 19:07:48
【问题描述】:

我正在尝试使用 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));
 }

平面列表代码:

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

该代码给了我以下我想要的结果(忽略糟糕的样式):

但每当我尝试发送消息时,它都会正确添加到数据库中,但平面列表会更新以显示:

上一条消息和新消息多次呈现的位置。将数据库中的新项目呈现到平面列表中的最佳方法是什么?

【问题讨论】:

    标签: javascript react-native firebase-realtime-database expo react-native-flatlist


    【解决方案1】:

    查看您的代码,我找不到您在哪里初始化 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!']
    

    解决此问题的建议是只为数组分配新值,因此您可以执行childData = snapshot.val() 之类的操作,而不是使用push

    我还建议您使用 console.log 调试代码,以了解 snapshot.val()childDatathis.state.messages 正在检索的内容

    希望对你有帮助

    编辑: 再次阅读,一个可能的问题还可能是由于 JS 是同步的,因此在您的 forEach 完成之前调用了您的 setState。解决方案可能是使用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
      });
     (...)
    

    以上面的代码为例

    希望对你有帮助

    【讨论】:

    • 太棒了,非常感谢您的意见。明天我会尝试实施您的建议,如果我能实现它,我会通知您。
    • 我得到了它的工作,我所要做的就是在 ref.on 的第一个函数的开头重新初始化子数据数组。这是更新的工作代码: ref.on('value', function(snapshot) { childData = []; snapshot.forEach(function (childSnapshot){ childData.push(childSnapshot.val()) });
    猜你喜欢
    • 1970-01-01
    • 2023-01-07
    • 2021-10-14
    • 1970-01-01
    • 2017-01-04
    • 2018-04-11
    • 2017-08-04
    • 2020-07-28
    • 1970-01-01
    相关资源
    最近更新 更多