Gerçek Zamanlı Dinleyiciler ve Çevrimdışı Kalıcılık
onSnapshot ile bir Firestore koleksiyonuna abone olun, arayüzde canlı güncellemeler alın ve uygulamanın bağlantı olmadan önbelleğe alınmış verileri okuyabilmesi için çevrimdışı kalıcılığı etkinleştirin.
Gerçek Zamanlı Dinleyiciler ve Çevrimdışı Kalıcılık, CoddyKit'te ücretsiz bir React Native Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, React Native Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. React Native Academy kursu toplamda 4 dersten oluşur.
Gerçek Zamanlı Dinleyiciler ve Tek Seferlik Okumalar
Firestore verileri okumak için iki yöntem sunar: .get() ile tek seferlik okumalar ve .onSnapshot() ile gerçek zamanlı dinleyiciler. Gerçek zamanlı bir dinleyici, kalıcı bir bağlantıyı açık tutar ve ilk veri yüklemesi de dahil olmak üzere belge veya sorgu sonucu her değiştiğinde geri çağırma işlevinizi çalıştırır.
Verilere yalnızca bir kez ihtiyaç duyduğunuzda (örneğin uygulama başlatılırken kullanıcı ayarlarını yüklerken) .get() kullanın. Veriler sık değiştiğinde ve kullanıcı arayüzünün güncel kalması gerektiğinde (sohbet akışı veya canlı skor gibi) .onSnapshot() kullanın.
Tek Bir Belgeyi Dinleme
Belirli bir belgedeki değişiklikleri dinlemek için bir DocumentReference üzerinde .onSnapshot(callback) çağrısını yapın. Geri çağırma işlevi mevcut verilerle hemen çalışır ve belge her değiştiğinde yeniden çalışır.
.onSnapshot() bir abonelikten çıkma işlevi döndürür. Bunu bir değişkende saklayın ve bileşen kaldırıldığında dinleyiciyi durdurmak, böylece bellek sızıntılarını önlemek için useEffect temizleme işlevinde çağırın.
import { useEffect, useState } from 'react';
import firestore from '@react-native-firebase/firestore';
export function usePost(postId: string) {
const [post, setPost] = useState(null);
useEffect(() => {
const unsubscribe = firestore()
.collection('posts')
.doc(postId)
.onSnapshot((snapshot) => {
if (snapshot.exists) {
setPost({ id: snapshot.id, ...snapshot.data() });
}
});
return unsubscribe; // Stop listener on unmount
}, [postId]);
return post;
}Koleksiyon Sorgusunu Dinleme
Sonuç kümesindeki herhangi bir belge eklendiğinde, değiştirildiğinde veya kaldırıldığında canlı güncellemeleri almak için bir koleksiyon sorgusuna .onSnapshot() ekleyin. Geri çağırma işlevine iletilen QuerySnapshot, yalnızca değişenleri değil, eşleşen tüm belgeleri içerir.
Bu, bir belge her değiştiğinde snapshot.docs içinden listenin tamamını yeniden oluşturduğunuz anlamına gelir. Bu yaklaşım küçük ve orta boyutlu listeler için uygundur; ayrıca Firestore'un yerel önbelleği, önbelleğe alınmış veriler için ağ üzerinden gidiş-dönüş gerekmese bile işlemi hızlandırır.
useEffect(() => {
const unsubscribe = firestore()
.collection('messages')
.where('roomId', '==', roomId)
.orderBy('createdAt', 'desc')
.limit(50)
.onSnapshot((snapshot) => {
const messages = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setMessages(messages);
});
return unsubscribe;
}, [roomId]);Verimlilik için DocumentChange Kullanma
Her anlık görüntüde listenin tamamını yeniden oluşturmak yerine, tam olarak neyin eklendiğini, değiştirildiğini veya kaldırıldığını görmek için değişiklikler dizisini inceleyebilirsiniz. snapshot.docChanges() içindeki her girdinin bir type özelliği vardır: 'added', 'modified' veya 'removed'.
Bu yaklaşım, aynı anda yalnızca birkaç belgenin değiştiği büyük koleksiyonlarda daha verimlidir. Yerel durum dizisini tamamen değiştirmek yerine hedefli olarak güncellersiniz.
snapshot.docChanges().forEach((change) => {
const item = { id: change.doc.id, ...change.doc.data() };
if (change.type === 'added') {
setItems((prev) => [item, ...prev]);
} else if (change.type === 'modified') {
setItems((prev) => prev.map((i) => (i.id === item.id ? item : i)));
} else if (change.type === 'removed') {
setItems((prev) => prev.filter((i) => i.id !== item.id));
}
});Dinleyici Hatalarını Yönetme
.onSnapshot() hata yönetimi için ikinci bir bağımsız değişken kabul eder. Dinleyici başarısız olduğunda — genellikle Firestore Güvenlik Kuralları kaynaklı bir izin hatası nedeniyle — hata geri çağırma işlevi bir FirebaseError ile çalışır.
Yaygın hata kodları arasında permission-denied (güvenlik kuralları okumayı engelledi) ve unavailable (çevrimdışı ve önbelleğe alınmış veri yok) bulunur. Sessizce başarısız olmak yerine alternatif bir kullanıcı arayüzü gösterebilmeniz için her zaman bir hata işleyicisi sağlayın.
const unsubscribe = firestore()
.collection('private-data')
.onSnapshot(
(snapshot) => {
setData(snapshot.docs.map((doc) => doc.data()));
},
(error) => {
if (error.code === 'permission-denied') {
setError('You do not have access to this data.');
} else {
setError('Could not load data. Check your connection.');
}
}
);Firestore Çevrimdışı Kalıcılığı
React Native Firebase, mobil cihazlarda çevrimdışı kalıcılığı varsayılan olarak etkinleştirir. Bu, Firestore'un okuduğunuz veya dinlediğiniz tüm belgeleri cihazdaki yerel bir SQLite veritabanında önbelleğe aldığı anlamına gelir. Cihazda internet olmadığında okumalar, önbelleğe alınmış verileri hemen döndürür.
Bunu etkinleştirmek için herhangi bir yapılandırma yapmanız gerekmez — doğrudan çalışır. Önbellek boyutu sınırını (varsayılan 40 MB) denetleyebilirsiniz. Önbellek dolduğunda Firestore, en uzun süredir kullanılmayan belgeleri çıkarır. Ayrıca cacheSizeBytes: firestore.CACHE_SIZE_UNLIMITED ile sınırı sınırsız olarak ayarlayabilirsiniz.
import firestore from '@react-native-firebase/firestore';
// Configure cache size (call before any Firestore operations)
await firestore().settings({
cacheSizeBytes: firestore.CACHE_SIZE_UNLIMITED,
persistence: true, // enabled by default on mobile
});
// After this, all reads and writes work offline automaticallyÖnbellekten ve Sunucudan Okuma
Varsayılan olarak .get() önce sunucuyu dener, çevrimdışıysa önbelleğe geri döner. Bir kaynak seçeneği belirterek bu davranışı geçersiz kılabilirsiniz: { source: 'cache' } her zaman yerel önbellekten okur (anında, ağ bağlantısı olmadan), { source: 'server' } ise her zaman ağa bağlanır.
Yalnızca önbellekten okuma, mevcut verileri hemen görüntülerken yeni bir ağ isteğinin tamamlanmasını beklemek istediğiniz iyimser kullanıcı arayüzü düzenleri için kullanışlıdır. Belge önbellekte yoksa yalnızca önbellekten okuma işlemi hata verir.
// Always use cached data (instant, works offline)
const snapshot = await firestore()
.collection('posts')
.doc(postId)
.get({ source: 'cache' });
// Always fetch from server (throws if offline)
const freshSnapshot = await firestore()
.collection('posts')
.doc(postId)
.get({ source: 'server' });
// Default: server first, cache fallback
const snapshot2 = await firestore()
.collection('posts')
.doc(postId)
.get();Sorgu İmleçleriyle Sayfalama
Büyük koleksiyonlarda verileri sorgu imleçlerini kullanarak sayfalar halinde yükleyin: .startAfter(lastDocument). Yüklediğiniz son belgeye bir referans tutun ve sonraki sayfayı almak için bunu bir sonraki sorguya iletin. Buna imleç tabanlı sayfalama denir.
Son belge anlık görüntüsünü durumda saklayın. Kullanıcı listenin en altına kaydırdığında (FlatList'in onEndReached özelliği), son belgeden sonra başlayan yeni bir sorguyu tetikleyin. Yeni sonuçları mevcut listeye ekleyin.
const [posts, setPosts] = useState([]);
const [lastDoc, setLastDoc] = useState(null);
const [hasMore, setHasMore] = useState(true);
async function loadMore() {
if (!hasMore) return;
let query = firestore()
.collection('posts')
.orderBy('createdAt', 'desc')
.limit(20);
if (lastDoc) {
query = query.startAfter(lastDoc);
}
const snapshot = await query.get();
if (snapshot.empty) {
setHasMore(false);
return;
}
setLastDoc(snapshot.docs[snapshot.docs.length - 1]);
const newPosts = snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
setPosts((prev) => [...prev, ...newPosts]);
}Bileşik Dizinler
.where() ve .orderBy() işlemlerini farklı alanlarda birlikte kullandığınızda Firestore bir bileşik dizin gerektirir. Bu dizin olmadan sorgu, dizini otomatik olarak oluşturmanız için bir URL içeren failed-precondition hatası verir.
Bileşik dizinler firestore.indexes.json dosyasında yapılandırılır ve Firebase CLI ile dağıtılır. Geliştirme sırasında hata günlüğündeki URL'ye tıklamanız yeterlidir; Firebase dizini sizin için oluşturur. Üretim ortamında dizinleri her zaman kod üzerinden yönetin; böylece sürüm denetiminde tutulabilirler.
// This query requires a composite index on (userId ASC, createdAt DESC)
const snapshot = await firestore()
.collection('posts')
.where('userId', '==', userId)
.orderBy('createdAt', 'desc')
.get();
// If the index is missing, you see:
// FirebaseError: The query requires an index.
// https://console.firebase.google.com/project/.../firestore/indexes?...
// Click the link to auto-create the indexEkran Değişikliğinde Dinleyicilerin Ayrılması
Gerçek zamanlı dinleyiciler bant genişliği ve pil tüketir. Kullanıcı bir ekrandan ayrıldığında bunları ayırmak için useEffect yerine React Navigation'ın useFocusEffect kancasını kullanın. useFocusEffect, ekran odaklandığında etkiyi çalıştırır ve ekran odağı kaybettiğinde temizleme işlemini gerçekleştirir.
Böylece yalnızca ilgili ekran görünürken etkin bir Firestore dinleyicisi tutarsınız; kullanıcı ekrandan ayrılıp geri döndüğünde dinleyici duraklatılır ve yeniden kurulur.
import { useFocusEffect } from '@react-navigation/native';
import { useCallback } from 'react';
export function ChatScreen({ route }) {
useFocusEffect(
useCallback(() => {
// Start listener when screen is focused
const unsubscribe = firestore()
.collection('messages')
.onSnapshot(handleSnapshot);
// Stop listener when screen loses focus
return unsubscribe;
}, [route.params.roomId])
);
}Yerel Durumla İyimser Güncellemeler
Akıcı bir kullanıcı deneyimi için değişiklikleri Firestore yazma işlemi tamamlanmadan hemen önce yerel duruma uygulayın; buna iyimser güncelleme denir. Değişikliği anında gösterin, ardından sunucu yanıtı geldiğinde gerçek zamanlı dinleyicinin değişikliği doğrulamasına veya düzeltmesine izin verin.
Örneğin kullanıcı bir gönderiyi beğendiğinde, yerel durumdaki beğeni sayısını hemen artırın. Sunucuya yazma işlemi başarısız olursa sayıyı azaltarak yerel durumu geri alın ve bir hata bildirimi gösterin. Bu yaklaşım, yavaş bağlantılarda hissedilen gecikmeyi önler.
async function toggleLike(postId: string, currentlyLiked: boolean) {
// 1. Optimistically update local state
setLiked(!currentlyLiked);
setLikeCount((prev) => prev + (currentlyLiked ? -1 : 1));
try {
// 2. Persist to Firestore
await firestore().collection('posts').doc(postId).update({
likesCount: firestore.FieldValue.increment(currentlyLiked ? -1 : 1),
});
} catch (error) {
// 3. Revert on failure
setLiked(currentlyLiked);
setLikeCount((prev) => prev + (currentlyLiked ? 1 : -1));
Alert.alert('Error', 'Could not update like. Try again.');
}
}Hızlı Kontrol
Bu derste ele alınan React Native Mobil Geliştirme kavramlarını anlayıp anlamadığınızı test edin.
Ders Özeti
Bu derste şunları öğrendiniz: canlı veri güncellemeleri için gerçek zamanlı dinleyicilerin .onSnapshot() ile nasıl bağlanacağını, Firestore çevrimdışı kalıcılığının verileri çevrimdışı kullanım için otomatik olarak nasıl önbelleğe aldığını ve büyük koleksiyonların startAfter imleç tabanlı sayfalama kullanılarak nasıl sayfalanacağını. Sırada React Native uygulamalarının profilini çıkararak performans darboğazlarını ortadan kaldırmak var.
Yapay zeka eğitmeniyle JavaScript öğren — ücretsiz
Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.
- Kurslar
- 30
- Dersler
- 120
Sıkça Sorulan Sorular
“Gerçek Zamanlı Dinleyiciler ve Çevrimdışı Kalıcılık” dersi ücretsiz mi?
Evet — “Gerçek Zamanlı Dinleyiciler ve Çevrimdışı Kalıcılık” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve React Native Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. React Native Academy kursu toplamda 4 dersten oluşur.
“Gerçek Zamanlı Dinleyiciler ve Çevrimdışı Kalıcılık” dersinde ne öğreneceğim?
onSnapshot ile bir Firestore koleksiyonuna abone olun, arayüzde canlı güncellemeler alın ve uygulamanın bağlantı olmadan önbelleğe alınmış verileri okuyabilmesi için çevrimdışı kalıcılığı etkinleştir… React Native Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
React Native Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te React Native Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“Gerçek Zamanlı Dinleyiciler ve Çevrimdışı Kalıcılık” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu React Native Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her React Native Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- React Native Firebase'i Projenize Bağlama
- Firebase ile E-posta ve Telefon Kimlik Doğrulaması
- Firestore Belgelerini Okuma ve Yazma
- Gerçek Zamanlı Dinleyiciler ve Çevrimdışı Kalıcılık