Encontré un problema en mi aplicación de chat.
Trabajo cuando publico el documento del mensaje en la columna de mensajes, pero luego intento recuperar los documentos y renderizarlos. Obtengo una matriz vacía.
Revisé los documentos de FB y no noté ningún error de mi parte. También leí un artículo en el que me aconsejaron usar la biblioteca react-firebase con useCollectionData con la que obtuve el mismo resultado.
const [messages, loading] = useCollectionData( firestore.collection('messages').orderBy('createdAt') )Probé diferentes enfoques pero nada parece funcionar.
import React, { useState, useEffect } from 'react' import { auth, db, app } from '../../firebase.config' import { useAuthState } from 'react-firebase-hooks/auth' import { useCollectionData } from 'react-firebase-hooks/firestore' import { docs, onSnapshot, query, where, addDoc, collection, serverTimestamp, orderBy, getDocs } from 'firebase/firestore' import Message from '../Message/Message' import Spinner from '../Spinner/Spinner' import './chat.css' const Chat = () => { const [user, loading, error] = useAuthState(auth) const [value, setValue] = useState('') const [msgs, setMsgs] = useState([]) console.log('msgs>>>>', msgs) useEffect(() => { const fetchMsg = async () => { const messagesRef = collection(db, 'messages') const q = query( messagesRef, orderBy('timestamp', 'desc') ) const querySnap = await getDocs(q) let listings = [] querySnap.forEach((doc) => { return listings.push({ id: doc.id, data: doc.data(), }) }) setMsgs(listings) } fetchMsg() }, []) const sendMessage = async (e) => { e.preventDefault(); const docRef = await addDoc(collection(db, 'messages'), { uid: user.uid, displayName: user.displayName, photoURL: user.photoURL, text: value, createdAt: serverTimestamp() }) console.log(docRef) setValue('') } if (loading) { return <Spinner /> } return ( <> <div className='ch-wind'> {msgs.map((msg) => ( <Message key={msg.id} msg={msg} style={{ backgroundColor: user.uid === msg.uid ? '#A32cc4' : '#a1045a' }} /> ))} </div> <form className="ch-form" onSubmit={sendMessage}> <textarea value={value} className='ch-form-text' onChange={e => setValue(e.target.value)} placeholder='Enter your message here' /> <button className='ch-form-btn' > Send </button> </form> </> ) } export default ChatAl usar el gancho useEffect() , supongo que desea obtener los datos en tiempo real. Firestore tiene oyentes en tiempo real que puede usar. Puede escuchar un documento con el método onSnapshot() . Una llamada inicial que utiliza la devolución de llamada que proporciona crea una instantánea del documento inmediatamente con el contenido actual del documento único. Luego, cada vez que cambia el contenido, otra llamada actualiza la instantánea del documento. Vea el código a continuación:
useEffect(() => { const messagesRef = query(collection(db, 'messages'), orderBy('timestamp', 'desc')); onSnapshot(messagesRef, (snapshot) => { // Maps the documents and sets them to the `msgs` state. setMsgs(snapshot.docs.map(doc => ({ id: doc.id, data: doc.data() }))) }) }, []) Además, como lo señaló @CDoe, debe usar el mismo nombre de Fieldname que configuró en el método addDoc , como puede ver en el código anterior.
Luego, en la representación, algo como esto:
{msgs.map((msg) => ( // By setting the `doc.data()` to the object `data`, you should access it by `msg.data.<object_key>` <Message key={msg.id} msg={msg.data.text} style={{ backgroundColor: user.uid === msg.data.uid ? '#A32cc4' : '#a1045a' }} /> ))}Dejo algunos comentarios sobre el código para que se entienda mejor.
Para obtener más información sobre las actualizaciones en tiempo real, puede consultar esta documentación .
En la consulta, está intentando ordenar por timestamp de tiempo. Ese no es un campo que está creando en sendMessage .
Cuando un valor por el que está ordenando no existe en el documento, no regresará.
Tal vez quisiste ordenar por el valor createdAt .
const q = query( messagesRef, orderBy('createdAt', 'desc') )