代码之家  ›  专栏  ›  技术社区  ›  stor314

每当添加新数据时,Flatlist会多次重新发送来自FireBase的数据

  •  0
  • stor314  · 技术社区  · 6 年前

    我正在尝试使用react native和firebase构建聊天应用程序界面,更新从我的数据库中提取的数据时遇到问题。我可以将现有数据加载到我使用的明细表中:

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

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

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

    enter image description here

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

    1 回复  |  直到 6 年前
        1
  •  0
  •   soutot    6 年前

    查看您的代码,我找不到您在哪里初始化 childData

    假设您的数据库是正确的,那么看起来您没有清理 儿童数据 在分配到您的状态之前

    this.setState({
      messages: childData
    });
    

    所以当你的代码运行这个push时 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() 儿童数据 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
      });
     (...)
    

    以上面的代码为例

    希望有帮助