添加新评论重复呈现的评论

时间:2020-12-24 16:24:17

标签: javascript reactjs firebase firebase-realtime-database

所以,我正在尝试使用 Firebase 用 React 创建一个评论部分。

数据库结构如下:

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

基本上发生的事情是:

precomm postcomm

它只是再次加载已经加载的评论!

我在调用retrieveComments/useEffect/handleSubmit时试图清空评论状态但没有用,我不知道发生了什么:(

1 个答案:

答案 0 :(得分: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 将继续监听数据库的更改,并在有人发布或编辑评论时自动更新评论。