I am trying to learn firestore realtime functionality.
Here is my code where I fetch the data:
useEffect(() => {
let temp = [];
db.collection("users")
.doc(userId)
.onSnapshot((docs) => {
for (let t in docs.data().contacts) {
temp.push(docs.data().contacts[t]);
}
setContactArr(temp);
});
}, []);
Here is my database structure:
When I change the data in the database I am unable to see the change in realtime. I have to refresh the window to see the change.
Please guide me on what I am doing wrong.
>Solution :
Few issues with your useEffect hook:
-
You declared the
temparray in the way that the array reference is persistent, setting data with setter function fromuseStaterequires the reference to be new in order to detect changes. So yourtemparray is updated (in a wrong way btw, you need to cleanup it due to now it will have duplicates) but React is not detectign changes due to the reference to array is not changed. -
You are missing
userIdin thedependency arrayofuseEffect. If userId is changed – you will continue getting the values for old userId. -
onSnapshotreturns the unsubscribe method, you have to call it on component unMount (or on deps array change) in order to stop this onShanpshot, or it will continue to work and it will be a leak.
useEffect(() => {
// no need to continue if userId is undefined or null
// (or '0' but i guess it is a string in your case)
if (!userId) return;
const unsub = db
.collection("users")
.doc(userId)
.onSnapshot((docs) => {
const newItems = Object.entries(
docs.data().contacts
).map(([key, values]) => ({ id: key, ...values }));
setContactArr(newItems);
});
// cleanup function
return () => {
unsub(); // unsubscribe
setContactArr([]); // clear contacts data (in case userId changed)
};
}, [userId]); // added userId