Печать дубликатов списков после добавления нового документа в коллекцию пожарных - PullRequest
0 голосов
/ 08 ноября 2019

Когда компонент загружается, он извлекает все данные из определенной коллекции в firestore и хорошо их отображает. затем, когда я добавляю новый документ, он добавляет этот документ, но затем распечатывает их все (включая новый) в предыдущем списке.

Это мой первый настоящий проект по реагированию, и я вроде не в курсе. Я попытался сбросить состояние при загрузке компонента и вызове метода в разное время.

import React, { Component } from 'react';

// Database Ref
import Firebase from '../../Config/Firebase';

// Stylesheet
import '../View-Styles/views.scss';

// Componenents
import Post from '../../Components/Post/Post';
import EntryForm from '../../Components/EntryForm/EntryForm';

export class Gym extends Component {

    constructor() {
        super();

        this.collection = 'Gym';

        this.app = Firebase;
        this.db = this.app.firestore().collection('Gym');

        this.state = {
            posts: []
        };

        this.addNote = this.addNote.bind(this);
    };


    componentDidMount() {

        this.currentPosts = this.state.posts;

        this.db.onSnapshot((snapshot) => {
            snapshot.docs.forEach((doc) => {
                this.currentPosts.push({
                    id: doc.id,
                    // title: doc.data().title,
                    body: doc.data().body
                });
            });

            this.setState({
                posts: this.currentPosts
            });
        });
    };

    addNote(post) {
        // console.log('post content:', post );
        this.db.add({
            body: post
        })
    }



    render() {
        return (
            <div className="view-body">
                <div>
                    {
                        this.state.posts.map((post) => {
                            return(
                                <div className="post">
                                    <Post key={post.id} postId={post.id} postTitle={post.title} postBody={post.body} />
                                </div>
                            )
                        })
                    }
                </div>
                <div className="entry-form">
                    <EntryForm addNote={this.addNote} collection={this.collection} />
                </div>
            </div>

        )
    };
};

export default Gym;

Я пытаюсь получить его только для добавления нового документа в список, а не для отображения другого полного списка сновый документ. нет сообщений об ошибках.

Ответы [ 2 ]

0 голосов
/ 08 ноября 2019

Ваша проблема связана с вашей componentDidMount() функцией и использованием onSnapshot(). Каждый раз, когда происходит обновление вашей коллекции, все слушатели, прикрепленные с onSnapshot(), будут срабатывать. В своем слушателе вы добавляете каждый документ в моментальном снимке в существующий список. Хотя этот список начинается пусто, к каждому последующему изменению к списку добавляются все документы в коллекции (включая старые, а не только изменения).

Существует два способа обработкимоментальный снимок слушателя, когда он входит - либо очищайте существующий список и создавайте его заново при каждом изменении, либо обрабатывайте только изменения (новые записи, удаленные записи и т. д.).

В качестве примечания: при использовании onSnapshot()Рекомендуется сохранить возвращаемую функцию «отписаться» (например, this.stopChangeListener = this.db.onSnapshot(...)). Это позволит вам позже заморозить состояние вашего списка без получения дальнейших обновлений с сервера, позвонив по номеру someGym.stopChangeListener().

Метод воссоздания

Для простоты я бы рекомендовал использовать этометод, если вы не имеете дело с большим количеством предметов.

componentDidMount() {

    this.stopChangeListener = this.db.onSnapshot((snapshot) => {
        var postsArray = snapshot.docs.map((doc) => {
            return {
                id: doc.id,
                // title: doc.data().title,
                body: doc.data().body
            });
        });

        this.currentPosts = postsArray;
        this.setState({
            posts: postsArray
        });
    });
};

Метод повторных изменений

Этот метод зависит от условий гонки и открывает возможностьдесинхронизация с базой данных, если обрабатывается неправильно.

componentDidMount() {

    this.stopChangeListener = this.db.onSnapshot((snapshot) => {
        var postsArray = this.currentPosts.clone() // take a copy to work with.

        snapshot.docChanges().forEach((change) => {
            var doc = change.document;
            var data = {
                id: doc.id,
                // title: doc.data().title,
                body: doc.data().body
            });
            switch(change.type) {
              case 'added':
                // add new entry
                postsArray.push(data)
                break;
              case 'removed':
                // delete potential existing entry
                var pos = postsArray.findIndex(entry => entry.id == data.id);
                if (pos != -1) {
                  postsArray.splice(pos, 1)
                }
                break;
              case 'modified':
                // update potential existing entry
                var pos = postsArray.findIndex(entry => entry.id == data.id);
                if (pos != -1) {
                  postsArray.splice(pos, 1, data)
                } else {
                  postsArray.push(data)
                }
            }
        });

        this.currentPosts = postsArray; // commit the changes to the copy
        this.setState({
            posts: postsArray
        });
    });
};


В качестве примечания: я бы также рассмотрел возможность перемещения this.currentPosts = ... в функцию this.setState().
0 голосов
/ 08 ноября 2019

Когда вы используете onSnapshot () в Cloud Firestore, вы можете печатать только данные добавленные . Для вашего кода это должно быть что-то вроде:

       snapshot.docChanges().forEach(function(change) {
           if (change.type === "added") {
               console.log("Newly added data: ", change.doc.data());
           }

Кроме того, Firestore не загружает всю коллекцию каждый раз, когда добавляются новые данные, документы кэшируются и будут повторно использоваться при повторном изменении коллекции.

Для получения дополнительной информации, вы можете проверить этот ответ .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...