Estoy obteniendo algunos datos de firestore y todo funciona, pero hay un gran defecto que estoy tratando de resolver...
Solo puedo consolar el registro de datos una vez que presiono el botón "Leer datos" dos veces. ¿Alguna ayuda sobre cómo puedo hacer que espere a que tenga la respuesta antes de mostrarla?
Abajo está mi código, gracias de antemano.
import firebase from 'firebase/compat/app' import 'firebase/compat/firestore'; import { useState } from 'react'; export default function ReadToFirebase() { const [data, setData] = useState([]) const readData = () => { try { firebase .firestore() .collection('users') .onSnapshot(snapshot => { let changes = snapshot.docChanges() changes.forEach(change => { let data = change.doc.data() data = { username: data.userName, email: data.email } setData(oldArray => [...oldArray, data]) }) }) console.log('Data Read!') console.log(data); // return data } catch (error) { console.log(`Opps! Error querying data: \n\n ${error}`); alert(error) } } return ( <div className="p-4 grid place-items-center space-y-2"> <button onClick={readData} className="py-2 px-4 bg-gray-300 rounded-xl font-bold">Read Data</button> <div className="">{}</div> </div> ) }Su declaración de console.log está fuera de la función onSnapshot . Si haces algo como esto:
const readData = () => { try { firebase .firestore() .collection('users') .onSnapshot(snapshot => { let changes = snapshot.docChanges() changes.forEach(change => { let data = change.doc.data() data = { username: data.userName, email: data.email } setData(oldArray => [...oldArray, data]) }); console.log('Data Read!') console.log(data); }) // return data } catch (error) { console.log(`Opps! Error querying data: \n\n ${error}`); alert(error) } }Funcionará.
Dos cosas a tener en cuenta aquí:
map en lugar de forEach : const changedData = changes.map(change => { let data = change.doc.data() return { username: data.userName, email: data.email } }); setData(oldArray => [...oldArray, ...changedData])try/catch realmente el error del servidor, debe envolver su solicitud en una promesa. Algo como: const readData = () => { new Promise((resolve, reject) => { firebase.firestore().collection('users').onSnapshot(handleSnapshot(resolve, reject)()); }) .then(handleSuccessfulUsersFetch) .catch(handleErrorInUsersFetch); }Hay otras formas de lograrlo (por ejemplo, con async/await). Puede leer más sobre el manejo de errores en JS en este buen artículo: https://medium.com/walkme-engineering/javascript-error-handling-9fc1a2946119