
Cloud
Learning Level
Firestore provides real-time listeners that automatically sync data across all connected clients. Changes to documents or collections instantly propagate to every listener, enabling collaborative and live applications.
By the end of this lesson, you'll understand:
JavaScript:
import { doc, onSnapshot } from 'firebase/firestore';
const userRef = doc(db, 'users', 'user123');
const unsubscribe = onSnapshot(userRef, (doc) => {
console.log('Current data:', doc.data());
});
// Stop listening
unsubscribe();Python:
def on_snapshot(doc_snapshot, changes, read_time):
for doc in doc_snapshot:
print('Current data:', doc.to_dict())
db.collection('users').document('user123').on_snapshot(on_snapshot)JavaScript:
const unsubscribe = onSnapshot(
doc(db, 'users', 'user123'),
(doc) => {
console.log('Document:', doc.data());
},
(error) => {
console.log('Error listening to document:', error);
}
);JavaScript:
import { collection, query, where, onSnapshot } from 'firebase/firestore';
const q = query(
collection(db, 'posts'),
where('author', '==', 'user123')
);
const unsubscribe = onSnapshot(q, (snapshot) => {
const posts = [];
snapshot.forEach((doc) => {
posts.push({
id: doc.id,
...doc.data()
});
});
console.log('Current posts:', posts);
});Python:
def on_snapshot(docs, changes, read_time):
posts = []
for doc in docs:
posts.append({'id': doc.id, **doc.to_dict()})
print('Current posts:', posts)
db.collection('posts').where('author', '==', 'user123').on_snapshot(on_snapshot)JavaScript:
const unsubscribe = onSnapshot(
collection(db, 'users'),
(snapshot) => {
snapshot.docChanges().forEach((change) => {
if (change.type === 'added') {
console.log('New user:', change.doc.data());
}
if (change.type === 'modified') {
console.log('Modified user:', change.doc.data());
}
if (change.type === 'removed') {
console.log('Removed user ID:', change.doc.id);
}
});
}
);JavaScript:
import { collection, query, orderBy, onSnapshot, addDoc, serverTimestamp } from 'firebase/firestore';
// Listen to messages
const chatRef = collection(db, 'chats', 'room1', 'messages');
const q = query(chatRef, orderBy('timestamp', 'asc'));
const unsubscribe = onSnapshot(q, (snapshot) => {
const messages = [];
snapshot.forEach((doc) => {
messages.push({
id: doc.id,
...doc.data()
});
});
// Update UI with messages
displayMessages(messages);
});
// Send message
async function sendMessage(text) {
await addDoc(chatRef, {
text: text,
author: currentUser.id,
timestamp: serverTimestamp()
});
}JavaScript (automatically enabled for web):
import { enableIndexedDbPersistence } from 'firebase/firestore';
try {
await enableIndexedDbPersistence(db);
console.log('Offline persistence enabled');
} catch (err) {
if (err.code == 'failed-precondition') {
console.log('Multiple tabs open, persistence disabled');
} else if (err.code == 'unimplemented') {
console.log('Browser does not support persistence');
}
}JavaScript:
import { onSnapshot } from 'firebase/firestore';
// Store unsubscribe function
const listeners = [];
function startListening() {
const unsubscribe = onSnapshot(
doc(db, 'users', 'user123'),
(doc) => {
console.log('Updated:', doc.data());
}
);
listeners.push(unsubscribe);
}
function stopAllListeners() {
listeners.forEach(unsubscribe => unsubscribe());
listeners = [];
}
// In React cleanup
useEffect(() => {
const unsubscribe = onSnapshot(
collection(db, 'users'),
(snapshot) => {
// Update state
}
);
return () => unsubscribe();
}, []);JavaScript (Multi-user document):
import { doc, onSnapshot, updateDoc } from 'firebase/firestore';
const docRef = doc(db, 'documents', 'shared-doc');
// Listen to document changes
onSnapshot(docRef, (doc) => {
updateUIWithContent(doc.data().content);
});
// User edits content
async function updateContent(newContent) {
await updateDoc(docRef, {
content: newContent,
lastEdited: new Date(),
editedBy: currentUserId
});
}Good:
// Only listen to recent messages
const q = query(
collection(db, 'messages'),
orderBy('timestamp', 'desc'),
limit(100)
);Good:
useEffect(() => {
const unsubscribe = onSnapshot(...);
return () => unsubscribe();
}, []);onSnapshot(collection(db, 'users'), (snapshot) => {
const activeUsers = snapshot.docs
.map(doc => doc.data())
.filter(user => user.isActive);
});Explore Cloud Functions for server-side logic triggered by Firestore changes, or learn about authentication to secure real-time data.
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward