I am using nextjs and firebase for a project and would like to retrieve data from firestore. Im having a hard time fixing the ".map is not a function" and nothing seems to work. How can I solve this?
I appreciate any help
const [farmacy, setFarmacy] = useState([]);
const fetchData = async () => {
const db = Fire.firestore();
const data = await db.collection("Farmacies").get();
setFarmacy(data.map((doc) => doc.data()));
};
data is a QuerySnapshot object. As you can see from the linked API documentation, it doesn't have a method called "map". Maybe you wanted to do something with the docs array in the snapshot?
const querySnapshot = await db.collection("Farmacies").get();
const allData = querySnapshot.docs.map(doc => doc.data());
Related
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() }));
});
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]);
};
I'm trying to replace below code (ver8) to firebase SDK ver9 (modular style). but no success so far.
useEffect(() => {
const unsub = db
.collection("posts")
.doc("postId")
.collection("comments")
.orderBy("timestamp", "desc")
.onSnapshot((snapshot) => {
//update some state
});
return () => {
unsub();
};
}, []);
I tried to use query to access this sub collection together with orderBy by refer to following official example but couldn't find working solution, especially how to handle sub collection reference in query. (how can I realize "collection().doc().collection().orderBy().onSnapshot" in ver9 ?)
I'm really appreciated if someone give me a hint. BR
https://firebase.google.com/docs/firestore/query-data/listen
https://firebase.google.com/docs/firestore/query-data/order-limit-data
As far as I can see in the documentation for the collection function, you can pass in the entire path as a string.
So that should be something like:
...
const db = getFirestore();
const commentsRef = doc(db, "posts", postId, "comments");
#Frank-san Thank you very much for your hint. Now everything working fine with full path arguments (your hint) as like below.
useEffect(() => {
const q = query(
collection(db, "posts", props.postId, "comments"),
orderBy("timestamp", "desc")
);
const unSub = onSnapshot(q, (snapshot) => {
//Some process
});
return () => {
unSub();
};
}, []);
Thanks again and have a good day !
I know there is a similar question that exists here but it doesn't really answer the question on here. My code currently on get the last two documents in a collection.
const [recipedata, setRecipeData] = useState([]);
const fetchRecipes = async () =>{
const response = fire.firestore().collection("recipes");
const data = await response.get();
data.docs.forEach(item=>{
setRecipeData([...recipedata, item.data()])
})
}
useEffect(() => {
fetchRecipes();
}, [])
Again when I print (recipedata) it only show two objects in the array. Can anyone tell me why this might be happening?
The query is correct and should fetch all the documents in the collection. You should check the the collection again. Also modifying the code like this should be better so you are updating the recipes array only once.
const [recipedata, setRecipeData] = useState([]);
const fetchRecipes = async () =>{
const response = fire.firestore().collection("recipes");
const data = (await response.get()).docs.map(doc => doc.data());
console.log(data)
//Updating only once
setRecipeData(data)
}
useEffect(() => {
fetchRecipes();
}, [])
Please share your collection as well so we can try replicating any issue if it has something to do with Firestore.
I have been trying to push or store a FireStore array in one of my own arrays. I have tried a few versions of code, the first being this:
var data = [];
db.collection('Rooms')
.doc(code)
.get()
.then((docs) => data.push(docs.data()));
However, when I log the data variable, it comes out as an empty array. The second method I have tried is this:
var [data, setData] = useState([]);
db.collection("Rooms")
.doc(code)
.get()
.then((docs) => setData(docs.data()));
However this method seems to setData infinitely, so it is reading into my API infinitely, which I would like to avoid. The last method I tried was this:
var data = db.collection("Rooms").doc(code).get();
console.log(data);
But this just returns
Promise {
"_U": 0,
"_V": 0,
"_W": null,
"_X": null,
}
Could anyone help me with this, ideally I'd like to store the data of an array called "MovieArray" inside the document, but I can't even access the document, so even if you can just help me store the data of the whole document, it would be very helpful.
If you are using react, I would suggest using the hook. You also, don't really need to push objects to an array like that.
Here is an example of how to get some data and store the collection of data.
const Forum = () => {
const [posts, setPosts] = useState(null);
const collectIdsAndDocs = (doc) => {
return { id: doc.id, ...doc.data() };
};
useEffect(() => {
const getPost = async () => {
const snapshot = await firestore.collection('Posts').get();
const myPosts = snapshot.docs.map(collectIdsAndDocs);
console.log(myPosts);
setPosts({ myPosts });
};
const createPost = async (post) => {
const docRef = await firestore.collection('Posts').add(post);
const doc = await docRef.get();
console.log(doc);
};
createPost({ Title: 'My First Post', Content: 'My content' });
getPost();
}, []);
return (
// return some JSX
);
};
Why does this work?
When you get a collection, Firebase returns a snapshot of the collection.
This snapshot has a list of docs or an array if you will.
We then want to map over those docs constructing a new object that contains just the document data and the ID of individual doc. This is what the myPosts variable is.
Using the react state hook, you can set that object to the current state of Posts, in your case this would be rooms.
When you add something to the database, Firestore will return a reference to the newly added item. You can then call get() to get the document back if you need it.
Try changing to (see comment before this)
const [data, setData] = useState({});