2022-04-08
Firebase CRUD and Auth (version 9)
Collection of Firebase snippets for my future use
-
posts
title
content
owner
createdAt
modifiedAt
isPublished
-
users
email
password
Get started
- Go to Firebase console
- Add project
- Create database from
Firestore Database
(Cloud Firestore) menu on the left- I'm not using
Realtime Database
here - I can still listen for realtime updates with
Firestore Database
- I'm not using
Prep/config
npm i firebase
// firebase.js
import { initializeApp } from "firebase/app"
import { getFirestore } from "firebase/firestore"
import { getAuth } from "firebase/auth"
const firebaseConfig = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
}
const app = initializeApp(firebaseConfig)
const db = getFirestore(app)
const auth = getAuth(app)
export { db, auth }
CRUD
// import config from above
import { db } from "./firebase"
// VS Code will auto import if you start typing
import {
collection,
doc,
setDoc,
serverTimestamp,
getDoc,
onSnapshot,
deleteDoc,
query,
where,
orderBy,
limit,
} from "firebase/firestore"
Create - setDoc
// Document ID is auto-generated by Firebase
const docRef = doc(collection(db, "posts"))
await setDoc(docRef, {
title,
content,
createdAt: serverTimestamp(),
modifiedAt: serverTimestamp(),
})
If your field needs to be unique, set the value as document ID
// Document ID is set with given string
await setDoc(doc(db, "users", "set-the-userId-123"), {
email: "",
password: "",
})
// Document ID is set with given string
await setDoc(
doc(db, "users", "set-the-userId-123"),
// Convert Firebase custom UserImpl object -> JavaScript object
JSON.parse(JSON.stringify(userCredentials.user))
)
Read - getDoc (single document)
const docRef = doc(db, "users", post.owner)
const docSnap = await getDoc(docRef)
if (docSnap.exists) {
console.log(docSnap.data())
} else {
console.log("No such document!")
}
Read - getDocs (not realtime)
const colRef = collection(db, "posts")
const snapshot = await getDocs(colRef)
snapshot.docs.map((doc) => {
console.log(doc.data())
return doc.data()
})
Read - onSnapshot (realtime updates)
// Without query
const colRef = collection(db, "posts")
onSnapshot(colRef, (snap) => {
snap.docs.forEach((doc) => {
console.log(doc.id)
console.log(doc.data())
})
})
// Using query
const colRef = collection(db, "posts")
const q = query(colRef, where("isPublished", "==", "true"), orderBy("createdAt", "desc"), limit(10))
onSnapshot(q, (snap) => {
snap.docs.forEach((doc) => {
console.log(doc.id)
console.log(doc.data())
})
})
// Mixed with some react code
import { useState, useEffect } from "react";
export const PostList = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
const docRef = collection(db, "posts");
const q = query(docRef, orderBy("createdAt", "desc"));
const unsubscribe = onSnapshot(q, (snap) => {
setPosts(
snap.docs.map((doc) => ({
...doc.data(),
id: doc.id,
}))
);
});
return () => unsubscribe();
}, []);
return (
<div>
{posts && posts.map((post) => (
{post.title}
))}
</div>
);
}
Update - setDoc
const docRef = doc(db, "posts", post.id)
await setDoc(
docRef,
{
title: newTitle,
content: newContent,
modifiedAt: serverTimestamp(),
},
{ merge: true }
)
Delete - deleteDoc
const docRef = doc(db, "posts", post.id)
await deleteDoc(docRef)
Auth
import { db, auth } from "./firebase"
import {
onAuthStateChanged,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
sendPasswordResetEmail,
AuthErrorCodes,
} from "firebase/auth"
Signup
// Create user to Firebase `Authentication`
const userCredentials = await createUserWithEmailAndPassword(auth, "email", "password")
console.log(userCredentials.user)
// Add created user to Firebase `Firestore Database`
await setDoc(
doc(db, "users", userCredentials.user.uid),
// Convert Firebase custom UserImpl object -> JavaScript object
JSON.parse(JSON.stringify(userCredentials.user))
)
Login
const userCredentials = await signInWithEmailAndPassword(auth, "email", "password")
console.log(userCredentials.user)
Logout
await signOut(auth)
Password reset
await sendPasswordResetEmail(auth, "email")
Error handling
try {
const userCredentials = await signInWithEmailAndPassword(auth, "email", "password");
} catch (error) {
if (error.code == AuthErrorCodes.USER_DELETED) {
console.log("user-not-found");
} else if (error.code == AuthErrorCodes.INVALID_PASSWORD) {
console.log("wrong-password");
}
...
}
Setting an observer on the Auth object - onAuthStateChanged
// Mixed with some react code
// UerContext.js
export const UserProvider = ({ children }) => {
const [user, setUser] = useState(null);
useEffect(() => {
onAuthStateChanged(auth, (user) => {
if (user) {
console.log("onAuthStateChanged: " + user.email);
setUser(user);
} else {
console.log("onAuthStateChanged: no user");
setUser(null);
}
});
}, []);
...