Kritim Yantra
Jun 22, 2025
Ever built a to-do app that doesn’t update instantly when you add a task? Feels like sending a letter 🏷️ instead of a text 📲, right?
With Firestore, your React apps can sync data in real-time—no refresh needed! By the end of this guide, you’ll build a real-time CRUD app with:
✅ Create, Read, Update, Delete operations
✅ Live data sync (changes appear instantly)
✅ Optimized queries (fetch only what you need)
✅ Security rules (keep data safe)
Let’s turn your app into a real-time powerhouse!
Before we start:
npx create-react-app firestore-crud
) Firestore is like Google Sheets on steroids 📊—but for apps.
Run:
npm install firebase @react-firebase/firestore
Update firebase.js
:
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = { ... }; // Your config from last guide
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app); // Firestore instance
Now you’re ready to read/write data!
import { db } from "./firebase";
import { collection, addDoc } from "firebase/firestore";
const addTodo = async (text) => {
try {
const docRef = await addDoc(collection(db, "todos"), {
text: text,
completed: false,
createdAt: new Date(),
});
console.log("Todo added with ID:", docRef.id);
} catch (error) {
console.error("Error adding todo:", error);
}
};
Fetch todos once:
import { getDocs, collection } from "firebase/firestore";
const fetchTodos = async () => {
const querySnapshot = await getDocs(collection(db, "todos"));
querySnapshot.forEach((doc) => {
console.log(doc.id, "=>", doc.data());
});
};
Real-time updates (🔥 game-changer!):
import { onSnapshot } from "firebase/firestore";
useEffect(() => {
const unsubscribe = onSnapshot(collection(db, "todos"), (snapshot) => {
const todos = [];
snapshot.forEach((doc) => {
todos.push({ id: doc.id, ...doc.data() });
});
setTodos(todos); // Updates state automatically
});
return unsubscribe; // Cleanup on unmount
}, []);
import { doc, updateDoc } from "firebase/firestore";
const toggleTodo = async (id, completed) => {
await updateDoc(doc(db, "todos", id), {
completed: !completed,
});
};
import { deleteDoc, doc } from "firebase/firestore";
const deleteTodo = async (id) => {
await deleteDoc(doc(db, "todos", id));
};
import { query, where } from "firebase/firestore";
const q = query(
collection(db, "todos"),
where("completed", "==", false)
);
import { orderBy } from "firebase/firestore";
const q = query(
collection(db, "todos"),
orderBy("createdAt", "desc")
);
import { limit, startAfter } from "firebase/firestore";
const firstBatch = query(collection(db, "todos"), limit(10));
// Fetch next 10 after last doc
const nextBatch = query(
collection(db, "todos"),
startAfter(lastVisibleDoc),
limit(10)
);
Test mode is insecure! Add rules in Firebase Console → Firestore → Rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /todos/{todoId} {
allow read, write: if request.auth != null;
// Only the owner can edit their todos
allow create: if request.auth.uid == request.resource.data.userId;
}
}
}
Here’s a simple React Todo App using Firestore:
function TodoApp() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState("");
// Real-time listener (from Step 2)
useEffect(() => { ... }, []);
const handleSubmit = (e) => {
e.preventDefault();
addTodo(input); // From Step 2
setInput("");
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Add a todo"
/>
</form>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id, todo.completed)}
/>
<span>{todo.text}</span>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
✔ Firestore = Real-time NoSQL database for apps
✔ CRUD operations are simple with addDoc
, updateDoc
, deleteDoc
✔ Live updates with onSnapshot
(no refresh needed!)
✔ Secure data with Firebase Rules
Stuck? Ask below! 👇
#HappyCoding 💻🔥
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google