Reputation:
I'm using what seems to be standard code to get all docs from Firestore and populate my localStorage with results from 2 collections, items and ratings.
It works initially.
Only thing is the page stops working once it's refreshed, no errors in the console. It can't be a firebase error, I just want it to get items from the db. The page doesn't need to be refreshed but I need to design for the possibility that the user might do so.
Why does the code only work once? Is it something to do with the await part of the querySnapshot?
// ----------> firebase vars <----------------------------------
initializeApp(firebaseConfig);
export const db = getFirestore();
export const auth = getAuth();
export const colRefItems = collection(db, 'items');
export const colRefRating = collection(db, 'ratings');
// ----------> Sync - get VARS from firebase <----------------------------------
const lastUpdated = settings[0].firebase.updated;
const user = "xxxxxxxxx";
console.log('%cSYNC: Pre items load', 'color:#059f2d')
// ----------> Sync - get items from firebase <----------------------------------
const q2 = query(colRefItems,
where("created", ">=", lastUpdated),
where("user", "==", user),
orderBy("created")
)
const querySnapshot = await getDocs(q2).then().catch((e)=> console.log(e));
console.log('%cSYNC: After items await', 'color:#059f2d')
querySnapshot.forEach((doc) => {
j++; let dataJk = {
uid: doc.id, type: +doc.data().type, user: user, colour: +doc.data().colour, created: doc.data().created, desc: doc.data().desc
}; itemListSync.push(dataJk)
});
if(j>0)localStorage.setItem('items',JSON.stringify(itemListSync));console.log('%cSYNC: '+itemListSync.length+' item(s) synced from Firestore', 'color:#059f2d')
console.log('%cSYNC: After items loop', 'color:#059f2d')
// ----------> Sync - get ratings from firebase <----------------------------------
const q3 = query(colRefRating,
where('created', '>=', lastUpdated),
where("user", "==", user),
orderBy('created')
)
const querySnapshotRating = await getDocs(q3).then().catch((e)=> console.log(e));
console.log('%cSYNC: After ratings await', 'color:#059f2d')
querySnapshotRating.forEach((doc) => {
k++; let ratingData = {
uid: doc.id, rating: +doc.data().rating, created: doc.data().created, user: user
}; itemRatingSync.push(ratingData)
});
if(k>0)localStorage.setItem('ratings',JSON.stringify(itemRatingSync));console.log('%cSYNC: '+itemRatingSync.length+' rating(s) synced from Firestore', 'color:#059f2d')
console.log('%cSYNC: After ratings loop', 'color:#059f2d')
Upvotes: 0
Views: 599
Reputation: 1346
You need to use useEffect and setState to be able to render your data. you need to use an Asynchronous function to fetch data from Firestore. This can be achieved using two ways , one is using the getDocs() method which is a method to get the data once, other is onSnapshot() this sets a listener to receive data-change events which means Cloud Firestore will send your listener an initial snapshot of any changes to your documents, collections of documents, or the results of queries. See sample code below on how to implement the onSnapshot() method , your code probably seems to have an issue with sequence of calling the data and render function, which causes this issue, check the code for these ,you may pass log statements to see what is called first and then rectify the same.
useEffect(() => { const getLabels = async () => { const colRef = query(collection(db, '<collection-name>')) onSnapshot(colRef, (snapshot) => { setLabels(snapshot.docs.map(doc => ({ id: doc.id, data: doc.data() }))) }) } getLabels() }, [])
Also check the following examples of similar implementations:
Upvotes: 1