#javascript #reactjs #firebase #firebase-realtime-database
# #javascript #reactjs #огневая база #firebase-база данных в реальном времени
Вопрос:
Итак, я пытаюсь создать раздел комментариев с помощью React, используя firebase.
структура БД следующая:
Код страницы «проект»:
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>
)}
}
и в основном происходит следующее:
И он просто снова загружает уже загруженные комментарии!
Я пытался очистить состояние комментариев при вызове 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. Спасибо! Решил проблему, а также помог мне понять, что я делал неправильно!