FlatList повторяет данные из Firebase несколько раз при добавлении новых данных - PullRequest
0 голосов
/ 21 мая 2018

Я пытаюсь создать интерфейс приложения чата, используя реакционную нативную и 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 Ответ

0 голосов
/ 21 мая 2018

Глядя на ваш код, я не смог найти, где вы инициализируете вашу childData.

Если предположить, что ваша база данных верна, то похоже, что вы не очищаете 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() или 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
  });
 (...)

Рассмотрим приведенный выше код в качестве примера

Надеюсь, это поможет

...