Добавление нового комментария, дублирующего отображаемые комментарии

#javascript #reactjs #firebase #firebase-realtime-database

# #javascript #reactjs #огневая база #firebase-база данных в реальном времени

Вопрос:

Итак, я пытаюсь создать раздел комментариев с помощью React, используя firebase.

структура БД следующая:

db

Код страницы «проект»:

 import React , { useEffect, useState, useRef }from 'react'
import firebase from "firebase/app";
import "firebase/database";
import { useAuth } from '../contexts/AuthContext'

export default function ProjectPage(props) {
    const { currentUser } = useAuth()
    const [author, setAuthor] = useState({})
    const commentRef = useRef()
    const[comments, setComments] = useState([])
    const [loadingComment, setLoadingComment] = useState(0)

    useEffect(()=>{
        retrieveAuthor();
        retrieveComments()
        console.log(currentUser.uid)
    }, [loadingComment])

    function retrieveAuthor(){
        if(props.location.project){
            var user = firebase.database().ref('/users/' props.location.project.uid)
            user.once('value', (snapshot) => {
                setAuthor({name: snapshot.val().name, surname: snapshot.val().surname})
            })
        }
    }

    function retrieveComments(){
        if(props.location.project){
            var comments = firebase.database().ref('/projects/' props.location.project.uid   '/'   props.location.project.pid '/comments');
            comments.once('value', (snapshot)=>{
                snapshot.forEach((snap)=>{
                    const commentObj = snap.val()
                    setComments(comments => [...comments, commentObj])
                    console.log(comments)
                })
            })
        }
    }

    const handleSubmit = (e) =>{
        e.preventDefault()
        firebase.database().ref('/projects/'  props.location.project.uid   '/'   props.location.project.pid  '/comments/').push({
            author: currentUser.uid,
            comment: commentRef.current.value
        })
        commentRef.current.value = ''
        setLoadingComment(loadingComment   1)
    }

    if(! props.location.project){
        return <div>No project selected</div>
    }else {
        return (            
            <div>
                <h1><strong>{props.location.project.title}</strong></h1>
                <div className='row w-100 h-100'>
                    <div className='col card m-3 ml-4 p-3'>
                        <div className='row text-center align-item-center mx-auto'>Comment Section</div>
                        <div className='card'>
                            {comments amp;amp; comments.map(comment=>{
                                console.log(comment)
                                return <div>{comment.comment}</div>
                            })}
                        </div>
                        <form onSubmit = {handleSubmit}>
                        <div className="input-group mb-3">
                            <input ref= {commentRef} type="text" className="form-control" placeholder="Your comment..." aria-label="Recipient's username" aria-describedby="basic-addon2"/>
                            <div className="input-group-append">
                                <button className="btn btn-outline-secondary">Add</button>
                            </div>
                        </div>
                        </form>
                    </div>
                    <div className='col-9'>
                        <div className = 'row'>
                            <div className='col'><strong>Description: </strong>{props.location.project.description}</div>
                            <div className='col'><strong>Author: </strong>{author.name} {author.surname}</div>
                        </div>
                        <div className='row card text-center align-item-center '>
                            <img className=' mx-auto w-100 h-100' src={props.location.project.url} />
                        </div>
                    </div>
                </div>
            </div>
        )}
    }
 

и в основном происходит следующее:

предварительный просмотр
postcomm

И он просто снова загружает уже загруженные комментарии!

Я пытался очистить состояние комментариев при вызове retrieveComments / useEffect / handleSubmit, но не сработало, я понятия не имею, что происходит: (

Ответ №1:

Когда вы прослушиваете значение в Firebase, каждый раз, когда вызывается ваш обратный вызов, он получает полный снимок всех данных в местоположении. Таким образом, ожидается, что во второй раз вы получите новое сообщение ** и все сообщения, которые уже были там.

Поэтому вам нужно игнорировать текущее значение comments в состоянии и всегда использовать только информацию из базы данных для ее заполнения:

 function retrieveComments(){
    if(props.location.project){
        var comments = firebase.database().ref('/projects/' props.location.project.uid   '/'   props.location.project.pid '/comments');
        comments.once('value', (snapshot)=>{
            let msgs = [];
            snapshot.forEach((snap)=>{
                msgs.push(snap.val());
            })
            setComments(comments => msgs);
        })
    }
}
 

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

Комментарии:

1. Спасибо! Решил проблему, а также помог мне понять, что я делал неправильно!