Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

334
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda