I am making something which allows logged user to report their lost items to the firestore firebase. Now what I've done successfully registers details of the user's report to the 'reports'collection.
but everytime the same user reports another item, the details of previously reported item gets overwritten. I want it in such a way that the new report gets added to the same collection, without overwriting the previous one. Something like in an array, in which when u add an item, it doesn't get overwritten, but adds to the array
i have done this
await setDoc(doc(db,"reports",auth.currentUser.uid),{
description: descref.current.value,
email: auth.currentUser.email,
timestamp: serverTimestamp(),
}).then(async () =>{
if (image) {
const storageRef = ref(storage,`images/${ image.name auth.currentUser.uid }`)
const uploadTask = uploadBytesResumable(storageRef,image);
setimage(null);
uploadTask.on(
'state_changed',
null,
(err) => console.log(err),
() => {
// download url
getDownloadURL(uploadTask.snapshot.ref).then(async (url) => {
console.log(url);
//adding the image URL to collection
await setDoc(doc(db,'reports', auth.currentUser.uid ),{imgurl:url},{merge:true});
It looks like this
[(https://i.stack.imgur.com/SYo73.png)](https://i.stack.imgur.com/SYo73.png)
but whenever i upload new data, the previous one gets overwritten.
what i want is this
{
"posts": {
"0": {
"author": "gracehop",
"title": "Announcing COBOL, a New Programming Language"
},
"1": {
"author": "alanisawesome",
"title": "The Turing Machine"
}
}
}
can anyone help how to do this?
CodePudding user response:
Calling setDoc()
without merge: true
will overwrite the doc. You are also passing the user id as the doc id written this way. Try calling addDoc()
instead and use update after getting the download URL. Some of this also cleans up your async statements a bit:
const newDoc = doc(collection(db,"reports", auth.currentUser.uid));
await addDoc(newDoc, {}).then(() => {
if (image) {
const storageRef = ref(storage, `images/${image.name auth.currentUser.uid}`)
const uploadTask = uploadBytesResumable(storageRef, image);
setimage(null);
uploadTask.on(
'state_changed',
null,
(err) => console.log(err),
async () => {
const url = await getDownloadURL(uploadTask.snapshot.ref)
console.log(url)
await updateDoc(newDoc, { imgurl: url });
});
} else {
console.log(newDoc)
}
});
If you do not want each report to be saved by user id and instead just have the reports collection be an array of records, you should remove the user id portion.
const newDoc = doc(collection(db,"reports"));
// this will still work because the auto-generated ID is returned to the update method
CodePudding user response:
Assuming that the goal is to add new posts to reports/user.id/
without overwriting existing ones, try this way:
- First create a ref with an auto-generated ID for the new post under
reports/user.id
, this will be thenewPostRef
- Use
newPostRef
to set the report content - Upload the image and get download url (same as original)
- Use
newPostRef
again to update post with download url, using{ merge: true }
Example:
import { collection, doc, setDoc } from "firebase/firestore";
const newPostRef = doc(collection(db, "reports", auth.currentUser.uid));
await setDoc(newPostRef, {
description: descref.current.value,
email: auth.currentUser.email,
timestamp: serverTimestamp(),
}).then(async () => {
if (image) {
const storageRef = ref(storage, `images/${image.name newPostRef.id}`);
const uploadTask = uploadBytesResumable(storageRef, image);
setimage(null);
uploadTask.on(
"state_changed",
null,
(err) => console.log(err),
() => {
// download url
getDownloadURL(uploadTask.snapshot.ref).then(async (url) => {
console.log(url);
//adding the image URL to collection
await setDoc(newPostRef, { imgurl: url }, { merge: true });
});
}
);
}
});
The reports/user.id
will be a collection accepting multiple posts with auto IDs, hopefully that is the desired result here.