I want to delete document in firestore using deleteDoc(), but this not delete.
It's my code:
import { getFirestore } from "firebase/firestore";
import { getStorage, ref } from "firebase/storage";
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
let stRootDocument = `/${tipo}/${uid}`;
const refCol = doc(db,stRootDocument);
deleteDoc(refCol)
.then(() => {
console.log("Entire Document has been deleted successfully.")
})
.catch(error => {
console.log(error);
})
although, this dont delete.
My document don't have any subcollections, but don't delete, also I have tried:
to do the refer using:
const refCol = doc(db,"carousel","xgxxxxxxxxxxxxxxx");
and after to pass this refer in the deleteDoc Method but too don't delete.
other form:
deleteDoc(doc(colRef,uid)).then((objR) => {
return objR;
}).catch((error) => {
console.log(error);
});
but, this too doesn't delete.
Related
I'm trying to upload multiple images to firebase storage and store those urls in one firestore document as an array of strings, but I couldn't add all urls in same firestore document. Instead it's creating different documents for each firebase storage Url.
ImageUpload.js
import React, { useState } from "react";
import { toast } from "react-toastify";
import { db, storage } from "../firebase.config";
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
import {collection ,addDoc ,arrayUnion ,FieldValue ,updateDoc} from "firebase/firestore";
import { useNavigate } from "react-router-dom";
import "./style.css";
function ImageUpload() {
const [allImages, setAllImages] = useState([]);
function handleAllImage(e) {
e.preventDefault();
setAllImages(e.target.files);
console.log(e.target.files);
}
function MutipleUpload(e) {
e.preventDefault();
try {
const docRef = collection(db, "products");
{
for (let i = 0; i < allImages.length; i++) {
const storageRef = ref(storage, `productImages/${allImages[i].name}`);
const uploadTask = uploadBytesResumable(storageRef, allImages[i], {
contentType: allImages[i].type,
});
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log(progress);
},
(error) => toast.error(error.message),
() => {
getDownloadURL(uploadTask.snapshot.ref).then(
async (downloadURL) => {
await addDoc(docRef, {
imgUrl: arrayUnion(downloadURL),
});
}
);
}
);
}
}
toast.success("product added successfully!");
} catch (error) {
console.log(error.message);
}
}
return (
<>
<input
type="file"
multiple="multiple"
onChange={handleAllImage}
required
/>
<button onClick={MutipleUpload} type="submit" className="buy__btn mt-3">
Add Image
</button>
</>
);
}
export default ImageUpload;
Extra text cause error "It looks like your post is mostly code; please add some more details."
The problem is in this code:
getDownloadURL(uploadTask.snapshot.ref).then(
async (downloadURL) => {
await addDoc(docRef, {
imgUrl: arrayUnion(downloadURL),
});
}
);
Every time you call addDoc, Firestore create a new document in the collection.
If you instead want update an existing document, you have to:
Remember the document ID for the document you want to update.
Then call updateDoc on that document
To generate a document ID once and then update that all the time, have a look at the third code snippet in the documentation on adding a document:
In some cases, it can be useful to create a document reference with an auto-generated ID, then use the reference later. For this use case, you can call doc():
import { collection, doc, setDoc } from "firebase/firestore";
// Add a new document with a generated id
const newCityRef = doc(collection(db, "cities"));
// later...
await setDoc(newCityRef, data);
Applied to your use-case, that could look something like this:
const docRef = collection(db, "products");
const newDocRef = doc(docRef); // 👈 generate reference to a single new doc
{
for (let i = 0; i < allImages.length; i++) {
const storageRef = ref(storage, `productImages/${allImages[i].name}`);
const uploadTask = uploadBytesResumable(storageRef, allImages[i], {
contentType: allImages[i].type,
});
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log(progress);
},
(error) => toast.error(error.message),
() => {
getDownloadURL(uploadTask.snapshot.ref).then(
async (downloadURL) => {
await setDoc(newDocRef, { // 👈 Call setDoc, since the doc may not exist yet
imgUrl: arrayUnion(downloadURL),
}, { merge: true }); // 👈 tell it to merge values into any existing doc
}
);
}
);
}
}
I'm trying to interact with the database in a function, but I'm getting an error when trying to use the doc() function within a firebase function
The error im getting is: " Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).
"
See the code below and the function I'm getting the error on.
Im guessing in has something to do with not being able to use the db variable? But if I cant do that, how do I interact with the database?
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
import {
collectionGroup, doc, getDoc,
getDocs,
getFirestore,
query,
} from "firebase/firestore";
// Sendgrid Config
import sgMail from "#sendgrid/mail";
import {
ClientUserData,
Course,
EventType,
Task,
} from "../../src/views/types/interfaces";
import {startOfDay} from "date-fns";
const adminApp = admin.initializeApp();
const auth = adminApp.auth();
const db = getFirestore();
//THE FUNCTION IT FAILS ON
export const checkCourseForNewClientProgram = functions.pubsub.schedule("Every day").onRun(async () => {
const courses: Course[] = [];
const coursesByCompanies = query(collectionGroup(db, "courses"));
// eslint-disable-next-line max-len
const checkCourseForNewClientProgramSnapshot = await getDocs(coursesByCompanies);
checkCourseForNewClientProgramSnapshot.forEach((courseSnapshot) => {
const course = courseSnapshot.data() as Course;
if (course.events && course.events.length > 0) {
const courseEvents = course.events;
const todayDate = startOfDay(new Date()).getTime();
courseEvents.forEach((event) => {
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
// #ts-ignore
// eslint-disable-next-line max-len
const eventStart = convertFirebaseDateIntoJSDate(event.start.seconds).getTime();
if (todayDate === eventStart) {
courses.push(course);
}
if (event.type === EventType.TASK) {
const eventLessons = (event as Task).lessons;
if (eventLessons && eventLessons.length > 0) {
eventLessons.forEach((eventLesson) => {
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
// #ts-ignore
// eslint-disable-next-line max-len
const lessonStart = convertFirebaseDateIntoJSDate(eventLesson.start.seconds).getTime();
if (todayDate === lessonStart) {
courses.push(course);
}
});
}
}
});
}
});
let userIds: string[] = [];
courses.forEach((course) => {
if (course.users) {
userIds = course.users.map((userId) => userId);
}
});
const userEmails = await Promise.all(
userIds.map(async (userId) => {
// eslint-disable-next-line max-len
const userData = await getDocumentFromId<ClientUserData>("company_clients", userId);
return userData.email;
})
);
await Promise.all(
userEmails.map(async (userEmail) => {
const msg = {
to: userEmail,
from: "nicky#byplayart.dk",
templateId: "d-8609d087e96e42d5abe6991d19afb22d",
dynamic_template_data: {
email: userEmail,
toName: "Testing tasks",
fromName: "Unlimited Performance",
subject: "Du har en opgave der venter",
text: "Dette er din tekst",
},
};
try {
await sgMail.send(msg);
return {
success: true,
};
} catch (e) {
return {
success: false,
error: e,
};
}
})
);
});
With the Admin SDK version 9 you should use the namespaced syntax, similarly to the Client SDK v8. The corresponding reference for the Admin DSK is actually the Node.js one.
Your code should then been adapted as follows:
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
admin.initializeApp();
const db = admin.firestore();
export const checkCourseForNewClientProgram = functions.pubsub.schedule("Every day").onRun(async () => {});
const coursesByCompanies = db.collectionGroup("courses");
const checkCourseForNewClientProgramSnapshot = await coursesByCompanies.get();
checkCourseForNewClientProgramSnapshot.forEach((courseSnapshot) => {...});
//...
return null;
});
Don't forget to correctly terminate your Cloud Function, either by returning the Promise returned by the last Promise.all() call or a value (e.g. return null;) after all the asynchronous work is complete. This is a key point and I would suggest you read this part of the doc and watch the 3 videos about "JavaScript Promises" from the Firebase video series.
I have a code to create user with image and username to Firebase v8 and I can't replace it to Firebase v9.
Can someone help me? Thank you!
import { useState, useEffect } from 'react'
import { projectAuth, projectStorage, projectFirestore } from '../firebase/config'
import { useAuthContext } from './useAuthContext'
export const useSignup = () => {
const [isCancelled, setIsCancelled] = useState(false)
const [error, setError] = useState(null)
const [isPending, setIsPending] = useState(f`enter code here`alse)
const { dispatch } = useAuthContext()
// upload user thumbnail
const uploadPath = `thumbnails/${res.user.uid}/${thumbnail.name}`
const img = await projectStorage.ref(uploadPath).put(thumbnail)
const imgUrl = await img.ref.getDownloadURL()
// add display AND PHOTO_URL name to user
await res.user.updateProfile({ displayName, photoURL: imgUrl })
import {st, db} from '../firebase/config'
import { getDownloadURL, ref, uploadBytesResumable } from 'firebase/storage';
import { doc, setDoc } from 'firebase/firestore';
const _storageRef = ref(st, "thumbnails/" + res.user.uid + "/" + thumbnail.name)
const _uploadTask = uploadBytesResumable(_storageRef, file);
_uploadTask.on("state_changed", (snapshot) => {
console.log((snapshot.bytesTransferred/snapshot.totalBytes) * 100)
},(error) => {
console.error(error)
}, async () => {
await getDownloadURL(_storageRef)
.then((url) => {
//update database with the new image url
console.log(url)
//setDoc(doc(db, "users", uid), {
// photoURL: url
// }, {merge: true}) <- to not erase the rest of the values like displayName
})
.catch(error => console.error(error))
})
The documentation has examples of both V8 (namespaced) and V9 (Modular) syntax. You can just switch to modular tab for reference. For this case, try refactoring the code as shown below:
import { ref, uploadBytes } from "firebase/storage"
import { updateProfile } from "firebase/auth"
const storageRef = ref(projectStorage, `thumbnails/${res.user.uid}/${thumbnail.name}`);
// 'file' comes from the Blob or File API
// uploadBytes() instead of .put()
uploadBytes(storageRef, file).then(async (snapshot) => {
console.log('Uploaded a blob or file!');
// updateProfile() is now a top-level function
// and not a method on User object
await updateProfile(res.user, {
displayName: name
});
console.log("User profile updated")
});
Also do ensure that you've initialized auth and storage using getAuth() and getStorage() respectively.
Checkout:
Upload files with Cloud Storage on Web
Update user profile using Firebase Modular SDK
why every time I try to access the index of my array it returns undefined? Also, I've tried to check it using type of it also returns object instead of array.
import { createAsyncThunk } from '#reduxjs/toolkit';
import { firestore } from 'firebase/firebaseConfig';
const RETRIEVE_COMMENTS = createAsyncThunk('retrieveComments', async ({ docID }) => {
try {
let retrievedComments = []
const comments = await firestore
.collection('products')
.doc(docID)
.collection('comments')
.orderBy("timestamp")
comments.onSnapshot(snapshot => {
snapshot.forEach((res) => retrievedComments.push(res.data()))
})
console.log(retrievedComments[0])
} catch (error) {
console.log(error)
}
})
export default RETRIEVE_COMMENTS
snapshot -> constantly listens to the collection
use the Promise returned from your write operation by attaching a .then()
If you want to receive snapshot events when the document or query metadata changes, pass a listen options object when attaching your listener:
db.collection("cities").doc("SF")
.onSnapshot({
// Listen for document metadata changes
includeMetadataChanges: true
}, (doc) => {
// ...
});
in your case :
import { createAsyncThunk } from '#reduxjs/toolkit';
import { firestore } from 'firebase/firebaseConfig';
const RETRIEVE_COMMENTS = createAsyncThunk('retrieveComments', async ({ docID }) => {
try {
let retrievedComments = []
const comments = await firestore
.collection('products')
.doc(docID)
.collection('comments')
.orderBy("timestamp")
comments.onSnapshot(snapshot => {
snapshot.forEach((res) => retrievedComments.push(res.data()))
}).then(doc => console.log(doc))
console.log(retrievedComments[0])
} catch (error) {
console.log(error)
}
})
export default RETRIEVE_COMMENTS
i am sorry if that not what you need I can not comment on your question I do not have more than 50 REPUTATION to comment
I am trying to log a user out and I am getting this error. I even tried to unsubscribe() but maybe I am doing it wrong because I am getting this error Uncaught Error in onSnapshot:, [FirebaseError: Missing or insufficient permissions.] Please can I get someone's help on how exactly to do this because I am really lost.
This is my code:
import { PURGE } from "redux-persist";
const Settings = () => {
const currentUser = firebase.auth().currentUser.uid;
const unsubscribeUser = firebase
.firestore()
.collection("Users")
.doc(currentUser)
.onSnapshot((doc) => {
//do things
});
const unsubscribePosts = firebase
.firestore()
.collection("Posts")
.doc(currentUser)
.onSnapshot((doc) => {
//do things
});
const SignOut = () => {
unsubscribeUser();
unsubscribePosts();
dispatch(reset([]));
dispatch({
type: PURGE,
key: "root",
result: () => null,
});
firebase.auth().signOut();
};
return <Button onPress={SignOut} title="Delete and Logout" />;
};
export default Settings;