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]);
Advertisement
Answer
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) => { // ... })