I'm always excited to take on new projects and collaborate with innovative minds.
+1 234 567 890
https://botble.com
123 Main Street, New York, NY 10001
Bu yazıda, React’ta useSyncExternalStore kancası ile hydration uyumsuzluklarını nasıl önleyebileceğimizi, aynı zamanda Suspense ve useDeferredValue
Hydration, React’ın sunucu tarafında oluşturulan HTML çıktısını tarayıcıda interaktif bileşenlerle eşleştirmesi sürecidir.
Yani sayfa ilk açıldığında, kullanıcı aslında statik bir HTML görür. Ardından React bu yapıyı “canlandırır” ve butonlar, inputlar gibi etkileşimli hale getirir.
Ancak bazen sunucuda render edilen HTML ile istemcide oluşturulan React ağacı birebir uyuşmaz. Bu durumda React “hydration mismatch” hatası verir veya bileşeni yeniden render etmek zorunda kalır.
useSyncExternalStore
Nedir?useSyncExternalStore
, React’ın 18 sürümüyle birlikte eklenen bir hook’tur.
Dış veri kaynaklarıyla (örneğin global store, event emitter, vs.) SSR + hydration uyumlu bir şekilde çalışmayı sağlar.
Temel kullanımı şöyle görünür:
const isSSR = React.useSyncExternalStore(
() => () => {}, // subscribe: değişiklikleri dinler
() => false, // getSnapshot: istemci tarafında çağrılır
() => true // getServerSnapshot: sunucu + hydration sırasında çağrılır
)
Bu yapı sayesinde React, sunucu ve istemci tarafındaki çıktılar arasında eşitlik sağlar.
Yani hydration sırasında ne bekleniyorsa, o değer döner — böylece mismatch oluşmaz.
useSyncExternalStore
ve Suspense Arasındaki TuzaklaruseSyncExternalStore
harika bir çözüm gibi görünse de, özellikle bileşeniyle birlikte kullanıldığında bazı problemler ortaya çıkar:
Suspense fallback’larının yanıp sönmesi
Sayfa önce sunucu çıktısını gösterir, ardından loading spinner görünür, sonra tekrar gerçek içerik gelir. Kullanıcı açısından bu “yanıp sönme” hoş bir deneyim oluşturmaz.
Henüz hydrate edilmemiş bileşenlere güncelleme gelmesi
Bazı bileşenler interaktif hale gelmeden önce store değişirse, hydration hataları oluşabilir. React bu durumda yeniden render yapmak zorunda kalır.
Kötü INP (Interaction to Next Paint) değerleriuseSyncExternalStore
eşzamanlı render tetiklediği için ana iş parçacığını bloke eder. Bu, etkileşimlerde gecikme yaratır.
Render zamanlamasının kontrolsüzleşmesi
Hook, React’ın “zaman dilimleme” (time slicing) avantajını devre dışı bırakır; performans düşebilir.
useDeferredValue
ile Birlikte KullanmakBu sorunları çözmek için useDeferredValue
hook’u devreye giriyor.
Yani useSyncExternalStore
’dan dönen değeri ertelenmiş bir şekilde yöneterek, hem hydration uyumsuzluklarını hem de performans sorunlarını önleyebiliriz.
İşte örnek uygulama:
const emptySubscribe = () => () => {}
const returnFalse = () => false
const trueOnServerOrHydration = () => true
function useIsSSR() {
const isSSRSync = React.useSyncExternalStore(
emptySubscribe,
returnFalse,
trueOnServerOrHydration
)
return React.useDeferredValue(isSSRSync)
}
function App() {
const isSSR = useIsSSR()
return isSSR ? "Server output" : "Client output"
}
İlk render’da (SSR + hydration
aşaması) isSSR
değeri true
olur.
Bu sayede React sunucudan gelen çıktıyı doğrudan kullanır → mismatch olmaz.
React daha sonra istemci tarafında isSSRSync = false
değerini üretir.
Ancak useDeferredValue
, bu değişimi hemen yansıtmaz → kullanıcı “yanıp sönen fallback” görmez.
Sonrasında React, eşzamanlı olmayan (concurrent) şekilde client tarafı içeriğe geçer.
Sonuç olarak:
Hydration hataları engellenir ✅
Suspense daha akıcı çalışır ✅
INP değeri korunur, kullanıcı deneyimi daha akıcı hale gelir ✅
Ek olarak, yazıda useMemoOne
gibi araçlarla bileşenlerin referanslarının sabit tutulması öneriliyor.
Bu, Suspense sınırları arasında gereksiz yeniden render’ları önleyerek performansı artırır.
React’ta SSR ve hydration süreçleri, kullanıcıya hızlı ve sorunsuz bir ilk yükleme deneyimi sunmak için kritik öneme sahiptir.useSyncExternalStore
, bu süreci kontrol altına almak için güçlü bir araçtır — ancak doğru kullanılmadığında performans sorunlarına yol açabilir.
En iyi yaklaşım, bu hook’u useDeferredValue
ile birlikte kullanmaktır.
Bu sayede hem hydration hatalarından kurtulabilir hem de daha akıcı bir kullanıcı deneyimi elde edebilirsin.
Your email address will not be published. Required fields are marked *