What is CRUD?
CRUD stands for:
Operation |
Purpose |
Create |
Add a new document |
Read |
Fetch one or more documents |
Update |
Change existing document |
Delete |
Remove a document |
In Firebase Firestore, documents are stored in collections.
✅ SETUP FIRST
You must first initialize Firebase:
firebasedb.js
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey:
"YOUR_KEY",
authDomain:
"YOUR_PROJECT.firebaseapp.com",
projectId:
"YOUR_PROJECT_ID",
storageBucket:
"YOUR_BUCKET",
messagingSenderId:
"YOUR_SENDER_ID",
appId:
"YOUR_APP_ID"
};
Perfect. Here’s a clear explanation of each Firebase CRUD
method used with Firestore — no code, just explanations.
🔥 Firebase Firestore
CRUD: Explained Simply
✅ 1. Create (add data) → addDoc()
- Purpose:
Add a new document to a Firestore collection.
- What
it does:
- Automatically
creates a unique ID for the document.
- Stores
your data in Firestore under that ID.
- Example
use case: When you register a new product or user.
📌 Summary:
“I want to create a new record in Firestore — use addDoc().”
🟨 2. Read (get data) →
getDocs() or getDoc()
There are two variations:
a) getDocs()
- Purpose:
Fetch all documents from a specific collection.
- Returns:
A snapshot of all the documents in that collection.
- Use
case: Showing a list of all products or users.
b) getDoc()
- Purpose:
Fetch a single document by its ID.
- Use
case: When editing a specific user or item.
📌 Summary:
“I want to read one or all documents — use getDoc() or
getDocs().”
🔄 3. Update (edit data) →
updateDoc()
- Purpose:
Update fields inside an existing document.
- What
it does:
- You
provide the document's ID.
- You
specify which fields to update and their new values.
- Use
case: Editing a product's price or updating user details.
📌 Summary:
“I want to change some values in a document — use
updateDoc().”
❌ 4. Delete (remove data) →
deleteDoc()
- Purpose:
Remove a document from Firestore.
- What
it does:
- Deletes
a document permanently.
- You
must specify the document’s ID.
- Use
case: Deleting a user account or a product listing.
📌 Summary:
“I want to completely remove a document — use deleteDoc().”
🔑 Bonus: Helper Methods
🔹 collection()
- Purpose:
Refers to a collection (like a table in SQL).
- Needed
for: All operations (create, read, etc.) to tell Firebase where to
act.
🔹 doc()
- Purpose:
Refers to a specific document by ID inside a collection.
- Used
in: updateDoc(), deleteDoc(), getDoc().
🔁 Order of Usage in a
CRUD App
- addDoc()
→ to add new records
- getDocs()
/ getDoc() → to read data
- updateDoc()
→ to edit existing data
- deleteDoc()
→ to remove data
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
1. 🟢 CREATE – Add a Product
import { collection, addDoc } from
"firebase/firestore";
import { db } from "./firebasedb";
export const addProduct = async (name, price, company) =>
{
try {
await
addDoc(collection(db, "products"), {
name,
price,
company,
});
alert("Product added successfully!");
} catch (error) {
console.error("Error adding product:", error);
}
};
2. READ – Get All
Products
import { collection, getDocs } from
"firebase/firestore";
import { db } from "./firebasedb";
export const getProducts = async () => {
try {
const snapshot =
await getDocs(collection(db, "products"));
return
snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
} catch (error) {
console.error("Error fetching products:", error);
}
};
This will return an array like:
[
{ id: 'abc123',
name: 'iPhone', price: 999, company: 'Apple' },
{ id: 'xyz456',
name: 'Galaxy', price: 899, company: 'Samsung' },
]
3. 🟠 UPDATE – Modify a
Product
import { doc, updateDoc } from
"firebase/firestore";
import { db } from "./firebasedb";
export const updateProduct = async (id, updatedData) => {
try {
const ref =
doc(db, "products", id);
await
updateDoc(ref, updatedData);
alert("Product
updated!");
} catch (error) {
console.error("Update error:", error);
}
};
Example Usage:
updateProduct("abc123", {
name: "iPhone
15",
price: 1099,
});
4. 🔴 DELETE – Remove a
Product
import { doc, deleteDoc } from
"firebase/firestore";
import { db } from "./firebasedb";
export const deleteProduct = async (id) => {
try {
await
deleteDoc(doc(db, "products", id));
alert("Product deleted!");
} catch (error) {
console.error("Delete error:", error);
}
};
📝 Summary
Action |
Function Name |
Firestore Method |
Create |
addProduct() |
addDoc() |
Read |
getProducts() |
getDocs() |
Update |
updateProduct() |
updateDoc() |
Delete |
deleteProduct() |
deleteDoc() |
✅ Real-world Flow Example
Imagine you're building a Product Admin Panel:
- On
screen load → Call getProducts() to show all products.
- On
"Add Product" → Call addProduct(name, price, company)
- On
"Edit" → Call updateProduct(id, updatedData)
- On
"Delete" → Call deleteProduct(id)
Perfect! Here's a complete working Firebase CRUD example
using React Native (with Expo) for a Product Admin Panel,
including UI and step-by-step explanations.
🔧 1. Project Setup
- Install
Required Packages:
npx create-expo-app product-admin
cd product-admin
npm install firebase
📁 2. File Structure
project-root/
│
├── config/
│ └──
firebasedb.js ← Firebase setup
│
├── screens/
│ ├── Home.js ← Product list + delete/edit
│ ├── AddProduct.js ← Add or Update product
│
├── App.js
🔥 3. firebasedb.js
// config/firebasedb.js
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey:
"YOUR_KEY",
authDomain:
"YOUR_PROJECT.firebaseapp.com",
projectId:
"YOUR_PROJECT_ID",
storageBucket:
"YOUR_BUCKET",
messagingSenderId:
"YOUR_SENDER_ID",
appId:
"YOUR_APP_ID"
};
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
📜 4. App.js – Navigation
Setup
import { NavigationContainer } from
'@react-navigation/native';
import { createNativeStackNavigator } from
'@react-navigation/native-stack';
import Home from './screens/Home';
import AddProduct from './screens/AddProduct';
const Stack = createNativeStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="AddProduct" component={AddProduct}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
🏠 5. Home.js – List
Products + Delete/Edit
// screens/Home.js
import { View, Text, FlatList, Button } from
"react-native";
import { useEffect, useState } from "react";
import { db } from "../config/firebasedb";
import { collection, getDocs, deleteDoc, doc } from
"firebase/firestore";
export default function Home({ navigation }) {
const [products,
setProducts] = useState([]);
const fetchProducts
= async () => {
const snapshot =
await getDocs(collection(db, "products"));
const list =
snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
setProducts(list);
};
const handleDelete =
async (id) => {
await
deleteDoc(doc(db, "products", id));
fetchProducts();
// refresh list
};
useEffect(() => {
fetchProducts();
}, []);
return (
<View style={{
padding: 20 }}>
<Button
title="Add New Product" onPress={() =>
navigation.navigate("AddProduct")} />
<FlatList
data={products}
keyExtractor={item => item.id}
renderItem={({
item }) => (
<View
style={{ marginVertical: 10, borderBottomWidth: 1, paddingBottom: 10 }}>
<Text>Name: {item.name}</Text>
<Text>Price: {item.price}</Text>
<Text>Company: {item.company}</Text>
<Button
title="Edit" onPress={() =>
navigation.navigate("AddProduct", { product: item })} />
<Button
title="Delete" color="red" onPress={() =>
handleDelete(item.id)} />
</View>
)}
/>
</View>
);
}
➕ 6. AddProduct.js – Add / Edit
Product
// screens/AddProduct.js
import { View, TextInput, Button, Alert } from
"react-native";
import { useEffect, useState } from "react";
import { db } from "../config/firebasedb";
import { collection, addDoc, updateDoc, doc } from
"firebase/firestore";
export default function AddProduct({ navigation, route }) {
const existing =
route.params?.product;
const [name,
setName] = useState("");
const [price,
setPrice] = useState("");
const [company,
setCompany] = useState("");
useEffect(() => {
if (existing) {
setName(existing.name);
setPrice(String(existing.price));
setCompany(existing.company);
}
}, [existing]);
const handleSubmit =
async () => {
if (!name ||
!price || !company) {
Alert.alert("Please fill all fields");
return;
}
if (existing) {
const docRef =
doc(db, "products", existing.id);
await
updateDoc(docRef, { name, price: Number(price), company });
Alert.alert("Product Updated");
} else {
await
addDoc(collection(db, "products"), { name, price: Number(price),
company });
Alert.alert("Product Added");
}
navigation.navigate("Home");
};
return (
<View style={{
padding: 20 }}>
<TextInput
placeholder="Name" value={name} onChangeText={setName} style={{
borderBottomWidth: 1, marginBottom: 10 }} />
<TextInput
placeholder="Price" value={price} onChangeText={setPrice}
keyboardType="numeric" style={{ borderBottomWidth: 1, marginBottom:
10 }} />
<TextInput
placeholder="Company" value={company} onChangeText={setCompany}
style={{ borderBottomWidth: 1, marginBottom: 20 }} />
<Button
title={existing ? "Update Product" : "Add Product"}
onPress={handleSubmit} />
</View>
);
}
✅ How It Works
Action |
File |
What Happens |
Show products |
Home.js |
Calls getDocs() and shows data in a list |
Add product |
AddProduct.js |
Calls addDoc() to save new data |
Edit product |
AddProduct.js |
Calls updateDoc() if existing data present |
Delete product |
Home.js |
Calls deleteDoc() with product ID |
getDoc
getDoc() — What It Does
getDoc() is used to read a single document from
Firestore.
Purpose
- To
fetch one specific document using its path (collection + document
ID).
- Useful
when you know the ID of the document you want.
Syntax Overview
import { doc, getDoc } from "firebase/firestore";
const docRef = doc(db, "products",
"abc123");
const docSnap = await getDoc(docRef);
Returns
It returns a DocumentSnapshot object, which includes:
- exists():
to check if the document actually exists.
- data():
the actual content of the document.
- id:
the document ID.
How It Works
- You
create a document reference using doc().
- You
call getDoc() and pass the reference.
- Firebase
sends back the document's snapshot if it exists.
- You
extract the data using .data().
Real-World Use Case
- Admin
Panel: Fetch and edit details of a specific product.
- Profile
Screen: Load the logged-in user’s data using their UID.
- View
Order: See full info of a single order by its ID.
Caution
- getDoc()
only reads once. It doesn’t keep listening for changes. For
real-time updates, you’d use onSnapshot() on a document.
Example
const docRef = doc(db, "users",
"userId123");
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
console.log("User data:", docSnap.data());
} else {
console.log("No
such document!");
}
0 Comments