Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

332
Vistas
Use firebase onSnapshot() in for loop?

The below code works for getting my data from firestore. I'm trying to update this to use onSnapshot() instead of of get(). Maybe the core of my confusion is onSnapshot() doesn't return a promise and I've tried just adding the listeners into an array but it seems the data doesn't get updated. How do I iterate over a for loop of onSnapshot()'s and render the results?

const [activityDataArray, setActivityDataArray] = useState([]);
const userActivityIds = userData.activities

useEffect(() => {
    let promises = [];
    for (const activityId of userActivityIds) {
        promises.push(getFirestoreData("activities", activityId));
    }
    Promise.all(promises).then(response => setActivityDataArray(response));
}, [userActivityIds]);

UPDATED CODE: When I console.log() the array it has my data, but I think this is a trick with chrome dev tools showing new information. I think when I call setActivityDataArray it's running it on an empty array and then it never gets called again. So the data doesn't render unless I switch to a different tab in my application and go back. Then it renders correctly (so I know the data is good, it's just a rendering issue). I think I need to re-render within onSnapshot() but how do I do this correctly?

const [activityDataArray, setActivityDataArray] = useState<any>([]);
const userActivityIds: string[] = userData.activities

useEffect(() => {
    let activityDataArrayDummy: any[] = []
    for (const i in userActivityIds) {
        firebase.firestore().collection("activities").doc(userActivityIds[i])
            .onSnapshot((doc) => {
                activityDataArrayDummy[i] = doc.data();
            });
    }
    console.log("activityDataArrayDummy", activityDataArrayDummy)
    setActivityDataArray(activityDataArrayDummy);
}, [userActivityIds]);
about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

Simply calling onSnapshot() in a loop should do it.

import { doc, onSnapshot } from "firebase/firestore";

for (const activityId of userActivityIds) {
  // get reference to document
  const docRef = doc(db, "activities", activityId)
  
  onSnapshot(docRef, (snapshot) => {
    // read and render data from snapshot
  })
}

However, if you ever need to unsubscribe from any of the listeners then you might have to store the Unsubscribe function returned by onSnapshot somewhere in state.


Just in case you have 10 or less items in userActivityIds then you can use onSnapshot() with a Query instead:

const q = query(collection(db, "activities"), where(documentId(), "in", userActivityIds));

onSnapshot(q, (querySnapshot) => {
  // ... 
})
about 4 years ago · Juan Pablo Isaza Denunciar

0

I went with this. Apparently state in react isn't guaranteed to be updated, so the proper way to setState with updated data is using a callback function.

https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

const [activityDataObj, setActivityDataObj] = useState({})
const userActivityIds: string[] = userData.activities

useEffect(() => {
    for (const i in userActivityIds) {
        firebase.firestore().collection("activities").doc(userActivityIds[i])
            .onSnapshot((doc) => {
                setActivityDataObj((activityDataObj) => {
                    return {...activityDataObj, [userActivityIds[i]]: doc.data()}
                })
            });
    }
}, [userActivityIds]);
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda