Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

336
Views
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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!