firebase onSnapshot not updating data in real time - javascript

I'm learning firebase and I'm baffled because I'm following the tutorial to the dot, literally copy and paste and though the following code:
// init firebase
initializeApp(firebaseConfig)
// init services
const db = getFirestore()
// collection ref
const colRef = collection(db, 'books')
// real time collection data
onSnapshot(colRef, (snapshot) => {
let books = []
snapshot.docs.forEach(doc => {
books.push({ ...doc.data(), id: doc.id })
})
console.log(books)
})
// adding docs
const addBookForm = document.querySelector('.add')
addBookForm.addEventListener('submit', (e) => {
e.preventDefault()
addDoc(colRef, {
title: addBookForm.title.value,
author: addBookForm.author.value,
})
.then(() => {
addBookForm.reset()
})
})
in the tutorial results in data being updated live (changes are reflected in the console, as users add/removes books), on my app changes are reflected only after refreshing the page.
I did some digging but only managed to find people with similar issue but no answer, i tried changing snapshot.docs.forEach(doc => ...) to snapshot.docChanges().forEach(doc => ...). same result.

Related

How to get the data of a query from firebase database in react-native

I am trying to list the data of each document that i am fetching from a firebase query, However I am being able to show the data through flatlist, Iwoudl love to iterate the data in another way in order to add it to a PDF that will be created from the app.
const [Annotations, setAnnotations] = useState(null);
useEffect(() => {
const q = query(
collection(db, "notifications"),
orderBy("createdAt", "desc")
);
console.log("Query:");
console.log(q);
onSnapshot(q, (test) => {
setAnnotations(test.docs);
});
}, []);
From the code above I am getting some unneccesary data, however I’d like to get the data of the document, hope you help me, thanks!
What you're seeing are the internals of the Firestore DocumentSnapshot and QueryDocumentSnapshot classes, which is indeed pretty meaningless.
If you only want to use the data:
onSnapshot(q, (test) => {
setAnnotations(test.docs.map((doc) => doc.data()));
});
If you want the data and document ID:
onSnapshot(q, (test) => {
setAnnotations(test.docs.map((doc) => { doc.id, ...doc.data() }));
});

How do I retrieve the UID's that I have placed as documents in my Firebase Cloud Firestore

I am currently using expo react-native to create a feed in which all user posts could be retrieved, I have come up with a solution to input all of the current users posts
const Posts = firebase.firestore().collection("posts").doc(user.uid).collection("userPosts");
const [users, setUsers] = useState([]);
useEffect(async () =>{
Posts
.onSnapshot(
querySnapshot => {
const users = []
querySnapshot.forEach((doc) => {
const { caption, creation, DownloadURL} = doc.data()
users.push({
id: doc.id,
caption,
creation,
DownloadURL,
})
})
setUsers(users)
}
)
}, [])
but I could not find a way to get retrieve all the UID's of all the users with posts in order for me to access all the posts, my database goes as follows:
posts(base collection with UID's of users)->userPosts( with UIDS of each post and fields for posts )
For reference I have also tried using the same format but to no avail as I tried to pass the values and it led to 'undefined', closest I have gone is get this on the console log:
The code for the above is here:
const AllUids = firebase.firestore().collection("posts");
const [uids, setUids] = useState([]);
useEffect(async () =>{
AllUids
.onSnapshot(
querySnapshot => {
const uids = []
querySnapshot.forEach((doc) => {
const {id} = doc.data()
uids.push({
id: doc.id,
id
})
})
setUids(uids)
}
)
}, [])
console.log(uids)
Both loading data from Firestore and setting modifying the state in a React app are asynchronous operations, so by the time your console.log(uids) runs neither of those will have completed yet.
The easiest way to log the uid value, is to use another effect that depends on that state variable:
useEffect(() => {
console.log(uids);
}, [uids]);
This has been coming up repeatedly in the past days, but I'm not sure why folks are suddenly bumping into this more than before.

Firebase onSnapshot in react error, "Expected type 'bc', but it was: a custom he object"

I was following this tutorial https://www.sitepoint.com/reddit-clone-react-firebase/.
Earlier it was really simple just call onSnapshot after the document is fetched, but here it is a separate function, and now here comes the issue, when I try to call that onSnapshot by passing document, but it always says,no matter what type of data I tried to pass it as the first param, it always says, it is not type of 'bc' which it expects.
FirebaseError: Expected type 'bc', but it was: a custom he object
useEffect(async () => {
const postsCollection = collection(db, "posts");
const orderedCollection = query(
postsCollection,
orderBy("createdAt", "desc")
);
try {
onSnapshot(
orderedCollection, // here I think the problem is!
(querySnapshot) => {
console.log("yahaan se problem hai");
console.log(querySnapshot);
const _posts = [];
querySnapshot.forEach((doc) => {
console.log(doc);
_posts.push({
id: doc.id,
...doc.data(),
});
});
console.log(_posts);
// setPosts(_posts);
},
(error) => {
console.log("error occured: ", error);
},
() => {
console.log("completed");
}
);
} catch (e) {
console.log("ye kya drama hai:", e);
} finally {
console.log("finally");
}
}, []);
Okey, so I had the same problem and I found a solution after struggling with the newest version of firebase for a while.
I don't know if you're using a class component or a functional one, in this example i'm using a funcional component but I assume it'll work the same if you replace the react hooks.
import { getFirestore, collection } from 'firebase/firestore'
const db = getFirestore();
const colRef = collection(db, "team")
const [results, setResults] = useState([]);
useEffect(() => {
let isMounted = true;
onSnapshot(colRef, (snapshot) => {
if (isMounted) {
const results= snapshot.docs.map((doc) => {return {...doc.data(), id: doc.id}});
setResults(results)
}
});
return () => { isMounted = false };
}, []);
This way your component'll listen to updates everytime the data changes, after that you can personalize it using querys but i wanted to show you a simple example so it's easy to understand.
I had the same problem, unfortunately, the above didn't help me. in my case I was actually importing form functions and types from '#firebase/firestore' and others from 'firebase/firestore'... this was done by autoImport. the moment I made all of them get the types and functions from the same place it worked instantly
These kind of errors occur usually when the functions aren't used the way they're supposed to. I can't really tell where the problem comes from in your code but you may try the getDocs method instead and a state variable to store your values
try this code.
const [Results, setResults] = useState([]);
useEffect(() => {
const FetchedPosts = async () => {
const querySnapshot = await getDocs(
collection(db, 'posts'),
orderBy("createdAt", "desc")
);
querySnapshot.forEach((doc) => {
setResults((prevState) => [...prevState, doc.data()]);
});
};
FetchedPosts();
}, []);

React-Native Firestore - Get user info for a comment section

I'm building an app using react-native and react-native-firebase and i'm running into an issue while trying to implement a comment section.
My tree of data is currently like that :
collection(comments)/doc(currentUser.uid)/collection(userComments)/doc(commentCreatorID)
Within this doc commentCreatorID there is all the data i need. So basically the content, a timestamp...
For this part everything works perfectly but in order to havethe commentCreator's infos stick with his post, i need to grab them somewhere else.
The way i do that is taking the doc(commentCreatorID), as it is the uid of this user and ask firestore to give me the data from the document with this same id within my "users" collection.
Here is my code :
const [comments, setComments] = useState([])
const [commentsReady, setCommentsReady] = useState([])
useEffect(() => {
setComments([])
setLoading(true)
firestore()
.collection('comments')
.doc(auth().currentUser.uid)
.collection('userComments')
.get()
.then((snapshot) => {
let comments = snapshot.docs.map(doc => {
const data = doc.data()
const id = doc.id
return {id, ...data}
})
setComments(comments)
})
.then(() => {
comments.forEach(comment => {
firestore()
.collection("users")
.doc(comment.id)
.get()
.then((snapshot) => {
const data = snapshot.data()
setCommentsReady({comments, ...data})
})
})
})
console.log(commentsReady)
setLoading(false)
}, [handleScroll4])
This doesn't seem to works well as for now. My log throw an empty array right into my face..
I'm grabbing each comment correctly tho and even each user's data corresponding to their uids.
I can log them once ForEach have been done.
But for some reason i can't have them set to my state commentsReady.
Did i miss something ?
Thanks for your time
The setters that the useState function returns are async. Copying data from one state to another is also an antipattern. Try using effects.
const TT = () => {
const [comments, setComments] = useState([]);
const [userInfos, setUserInfos] = useState([]);
const commentsView = comments.map(comment => {
// Reactively merge each comment with the appropriate user info
});
useEffect(() => {
firestore()
.collection('comments')
.doc(auth().currentUser.uid)
.collection('userComments')
.get()
.then((snapshot) => {
let comments = snapshot.docs.map(doc => {
const data = doc.data()
const id = doc.id
return {id, ...data}
});
setComments(comments);
});
}, []);
useEffect(async () => {
// Maybe keep a cache of fetched user datas, but not sure how this is architected
const snapshots = await Promise.all(comments.map(comment => {
return firestore()
.collection("users")
.doc(comment.id)
.get();
}));
setUserInfos(snapshots.map(snap => snap.data()));
}, [comments]);
};

Reading a value from Realtime Firebase

I have the following json structure:
Within "all" node I have an attribute "drinkId" and I'm trying to move it outside that child node bringing it one level up.
I'm trying to read the value without any luck
const cocktailRef= firebase
.database()
.ref("Ratings");
cocktailRef.once("value", (snapshot) => {
snapshot.forEach((child) => {
const drinkIdPass = child.ref.child("all").child("drinkId").value();
child.ref.update({ drinkId: drinkIdPass });
})
})
I've tried different variants of ".value()", same problem
There isn't any value() method on a DataSnapshot. It's val() Try refactoring your code like this:
const cocktailRef= firebase.database().ref("Ratings");
cocktailRef.once("value").then(async (snapshot) => {
const updates = { }
snapshot.forEach((child) => {
const drinkIdPass = child.val().all.drinkId
updates[`${child.key}/drinkId`] = drinkIdPass
})
await cocktailRef.update(updates)
console.log("Data updated")
})

Categories

Resources