How do you create a subcollection in Firebase Firestore? - javascript

I'm having troulbe figuring out how to add a subcollection to a document in my React App. I'm also getting the error that db.collection() is not a function. I'm trying to add the subcollection in the registerWithEmailAndPassword function. The Firebase Firestore documentation does not specify how to create a subcollection. Any help would be greatly appreciated thank you. Firebase config has been ommited to protect my API key.
import { initializeApp } from "firebase/app";
import {
GoogleAuthProvider,
getAuth,
signInWithPopup,
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
sendPasswordResetEmail,
signOut,
} from "firebase/auth";
import {
getFirestore,
query,
getDocs,
collection,
where,
addDoc,
Firestore,
doc,
DocumentReference,
setDoc
} from "firebase/firestore";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
const googleProvider = new GoogleAuthProvider();
const signInWithGoogle = async () => {
try {
const res = await signInWithPopup(auth, googleProvider);
const user = res.user;
const q = query(collection(db, "users"), where("uid", "==", user.uid));
const docs = await getDocs(q);
if (docs.docs.length === 0) {
await addDoc(collection(db, "users"), {
uid: user.uid,
name: user.displayName,
authProvider: "google",
email: user.email,
});
}
} catch (err) {
console.error(err);
alert(err.message);
}
};
const logInWithEmailAndPassword = async (email, password) => {
try {
await signInWithEmailAndPassword(auth, email, password);
} catch (err) {
console.error(err);
alert(err.message);
}
};
const registerWithEmailAndPassword = async (name, email, password) => {
try {
const res = await createUserWithEmailAndPassword(auth, email, password);
const user = res.user;
const userDoc = await addDoc(collection(db, "users"), {
uid: user.uid,
name,
authProvider: "local",
email,
});
db.collection("users").doc(userDoc.id).collection("test");
} catch (err) {
console.error(err);
alert(err.message);
}
};
const sendPasswordReset = async (email) => {
try {
await sendPasswordResetEmail(auth, email);
alert("Password reset link sent!");
} catch (err) {
console.error(err);
alert(err.message);
}
};
const logout = () => {
signOut(auth);
};
export {
auth,
db,
signInWithGoogle,
logInWithEmailAndPassword,
registerWithEmailAndPassword,
sendPasswordReset,
logout,
};

This code uses the classic, namespaced syntax of Firebase SDK version 8 and before:
db.collection("users").doc(userDoc.id).collection("test");
But the rest of your code uses the new modular syntax of Firebase SDK versions 9 and later. The equivalent there would be:
collection(doc(collection(db, "users"), userDoc.id), "test")
Or more concisely:
collection(db, "users", userDoc.id, "test")
The above creates a reference to the subcollection, but doesn't create the collection in the database yet. A collection is created once a document is written to it, and removed automatically once the last document is removed from it.
So you can create a document in test (and thus create test) with:
const testCollection = collection(db, "users", userDoc.id, "test");
addDoc(testCollection, { title: "hello world })

Related

Firebase JS db._checkNotDeleted is not a function

I'm writing a program that needs to add JSON data to my realtime firebase database, however I keep getting TypeError: db._checkNotDeleted is not a function at the ref() statement.
const { firebaseConfig } = require("./key");
const { EMAIL, PASSWORD } = require("./login");
const { initializeApp } = require("firebase/app");
const { getAuth, signInWithEmailAndPassword } = require("firebase/auth");
const { getDatabase, ref, update } = require("firebase/database");
async function setupFirebase(firebaseConfig, email, password) {
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
try {
await signInWithEmailAndPassword(auth, email, password);
} catch (e) {
console.error(e.message);
}
return getDatabase(app);
}
const db = setupFirebase(firebaseConfig, EMAIL, PASSWORD);
try {
const jsonData = require("foldername/filename");
update(ref(db, "machines/" + jsonData.MachineID), {
timestamp: jsonData.DateTimeMessage,
status: jsonData.Status,
});
} catch (e) {
console.error(e);
}
I have already tried to use set() or split my update to mimic the firebase docs as closely as possible but without any success. The problem seems to originate from the ref() statement itself as I cannot seem to use it in any way.

reactjs and firebase function db (database) not working on running

so this is my first project with firebase and im trying to send data to database but the function is not working:
const onSignUp = async (email, password, username) => {
try {
const authUser = await createUserWithEmailAndPassword(
firebase,
email,
password
);
db.collection("users").add({
owner_uid: authUser.user.uid,
usernames: username,
email: authUser.user.email,
profile_pic: await randomProfiles()
})
.then(() => {
console.log("CREATED");
this.props.phase(0);
})
.catch(() => {
console.log("ERROR");
alert("Bruh");
});
} catch (error) {}
};
const randomProfiles = async () => {
const respone = await fetch("https://randomuser.me/api");
const data = await respone.json();
return data.results[0].picture.large;
};
I think the problem might be in
db.collection("users").add({
THIS IS THE EDITED PART NEW CODE:
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyDVy_vUuhZN-qwMmTOUjsViQ4gW36q-Xxk",
authDomain: "social-media-app-d29f2.firebaseapp.com",
projectId: "social-media-app-d29f2",
storageBucket: "social-media-app-d29f2.appspot.com",
messagingSenderId: "103854538000",
appId: "1:103854538000:web:9c77e5a5f7de0c3cb7f995"
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
export { auth, db };
so this is my previous way of doing it
You are mixing Firebase SDKs V8 and V9 syntax.
const authUser = await createUserWithEmailAndPassword(...) is V9 syntax
while
db.collection("users").add(...) is V8 syntax.
Adapting your code as follows should do the trick. I don't know how you defined the firebase Object you pass to the createUserWithEmailAndPassword() method, so I included all the imports and initialization code. It's up to you to adapt this part.
import { initializeApp } from "firebase/app";
import { getAuth, createUserWithEmailAndPassword } from "firebase/auth";
import { getDatabase, collection, addDoc } from "firebase/firestore";
const app = initializeApp(firebaseConfig);
const onSignUp = async (email, password, username) => {
try {
const auth = getAuth(app);
const authUser = await createUserWithEmailAndPassword(
auth,
email,
password
);
const db = getDatabase(app);
await addDoc(collection(db, "users"), {
owner_uid: authUser.user.uid,
usernames: username,
email: authUser.user.email,
profile_pic: await randomProfiles()
});
this.props.phase(0);
} catch (error) {
console.log(error);
}
};

(Firebase Firestore)TypeError: n.indexOf is not a function

I'm trying to add another field value in a document but firebase returns TypeError: n.indexOf is not a function. Here's the code:
async function linkLCSN(cor, sn) {
try {
await setDoc(doc(db, "cor", cor), {
sn: sn,
}, {merge: true});
} catch(e) {
console.error(e);
}
}
I've already succeeded in doing this way but I don't know why this time it keeps giving me this error. This is the working code:
async function submitToDatabase(name, email, cor, cs, cn, concern) {
try {
//Set Datas
await setDoc(doc(db, "cor", cor), {
name: name,
email: email,
cor: cor,
courseSection: cs,
contactNumber: cn,
isViewed: false,
timestamp: serverTimestamp(),
}, {merge: true});
const docRef = await addDoc(collection(db, "cor", cor, "concerns"), {
concernData: concern,
});
console.log("Yung betlog nasa:" + docRef.id);
//Do page changes
let a = document.querySelector(".concern-main-container");
let b = document.querySelector(".concern-preview-container");
a.style.display = "none";
b.style.display = "block";
} catch(e) {
console.error(e);
//Custom Alert
}
}
I solved my problem by checking every type of params that passing to doc(), that params should not be Integer. It must be String
I'm assuming you are using v9 of firebase (modular version). It may sound silly, but make sure that you have initialized your app and that you are using a valid reference to a collection.
For example:
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
const config = {/** your firebase config properties **/};
const app = initializeApp(config);
const db = getFirestore(app);
Then to add a new document, you can do:
const createDocument = (collectionName, document) => {
const colRef = collection(db, collectionName);
return addDoc(colRef, document);
};
Remember the addDoc function returns a promise, so be sure to handle this is the caller of createDocument

How to use SignInWithRedirect with GoogleAuthProvider?

I am creating a Vue App (Vue version 2). I am using Firebase (Web version 9) as a database and for the authentication. I am using Google as Sign in method. On desktop I want to use the signInWithPopup method, which works perfectly fine. However they recommend using signInWithRedirect on mobile. I do not understand how this second method have to be used. Here is what I have done so far :
googleSignIn: async function () {
const auth = getAuth();
const provider = new GoogleAuthProvider();
try {
let result;
if (this.isMobile) {
await signInWithRedirect(auth, provider);
result = await getRedirectResult(auth);
if (result) {
console.log(result);
} else {
console.log("no result");
}
} else {
result = await signInWithPopup(auth, provider);
}
const googleUser = result.user;
const query = await db
.collection("users")
.where("email", "==", googleUser.email)
.get();
if (!query.empty) {
this.$store.dispatch("setUser", googleUser.reloadUserInfo);
this.$router.push({ path: "/dashboard" });
} else {
alert("impossible de se connecter");
}
} catch (err) {
console.log(err);
}
}
Here are my imports :
import { getAuth, signInWithPopup, signInWithRedirect, getRedirectResult, GoogleAuthProvider, } from "firebase/auth";
Use cicle life mounted:
mounted(){
authFire.getRedirectResult(authFire.auth)
.then((result)=>{
if(result!=null){
}
})
},

Firebase v9 auth.currentUser is null after creating the user

Here's my JS code:
import { ref } from "vue"
import { projectAuth } from '../firebase/config'
import { getAuth, createUserWithEmailAndPassword, updateProfile } from 'firebase/auth'
const error = ref(null)
const isPending = ref(false)
const signup = async(email, password, displayName) => {
error.value = null
isPending.value = true
try {
const res = createUserWithEmailAndPassword(projectAuth, email, password)
console.log(projectAuth.currentUser)
if (!res) {
console.log('Could not complete the signup')
throw new Error('Could not complete the signup')
}
console.log(projectAuth.currentUser)
await updateProfile(projectAuth.currentUser, {displayName})
error.value = null
isPending.value = false
return res
} catch(err) {
console.log('ERROR: ' + err.message)
error.value = err.message
isPending.value = false
}
}
const useSignup = () => {
return {error, signup, isPending}
}
export default useSignup
My Vue3 application is calling the signup function in this script whenever a user is signing up. The createUserWithEmailAndPassword function is successful and the user shows up in firebase. But I want to also add a display name to my user, so I'm trying to use the updateProfile function to do that but there's a problem.
The problem is the projectAuth.currentUser is null even after creating the user and I can't figure out why??
The createUserWithEmailAndPassword() method returns a promise. Since your function is async, try adding await:
const res = await createUserWithEmailAndPassword(projectAuth, email, password)
console.log(projectAuth.currentUser)
Alternatively, you can pass User object to updateProfile directly from res:
const { user } = await createUserWithEmailAndPassword(projectAuth, email, password)
await updateProfile(user, { displayName })

Categories