# React 19 Suspense ve Concurrent Rendering: Streaming SSR ve Mülakat Soruları 2026 > React 19 Suspense, concurrent rendering ve streaming SSR için kapsamlı rehber. use() API, useTransition, useDeferredValue öğrenin ve teknik mülakatlara hazırlanın. - Published: 2026-08-21 - Updated: 2026-08-21 - Author: Anthony Fillion-Maillet - Tags: react, suspense, concurrent-rendering, streaming-ssr, interview - Reading time: 12 min --- React 19 Suspense, uygulamaların asenkron işlemleri nasıl ele aldığını temelden değiştiriyor. Yükleme durumları, hata yönetimi ve veri çekme için deklaratif bir model sunuyor. Concurrent rendering ile birlikte Suspense, yoğun hesaplamalar sırasında UI'ı duyarlı tutarken daha hızlı içerik gösterimi sağlayan streaming SSR'i mümkün kılıyor. > **Temel Bilgi** > > Suspense sınırları, yükleme fallback'lerinin nerede görüneceğini tanımlar. Concurrent rendering, React'in düşük öncelikli işleri kesintiye uğratarak yüksek öncelikli etkileşimlerin (yazma, tıklama) duyarlı kalmasını sağlar. Birlikte, sunucudan HTML akışı ve aşamalı hidrasyonu mümkün kılarlar. ## Concurrent Rendering ve Senkron React Arasındaki Farklar React 18'den önce render senkrondu: React bir bileşen ağacını render etmeye başladığında, başka herhangi bir işi ele almadan önce bitirmek zorundaydı. Concurrent rendering, React'in önceliklere göre render'ı duraklatmasına, kesmesine ve devam ettirmesine izin vererek bu modeli kırıyor. [React dokümantasyonu](https://react.dev/blog/2022/03/29/react-v18#what-is-concurrent-react) concurrent rendering'i Suspense, transitions ve streaming SSR gibi özellikleri etkinleştiren bir arka plan mekanizması olarak tanımlıyor. Temel içgörü: React, aynı anda birden fazla UI versiyonu hazırlayabilir. ```tsx // TransitionExample.tsx import { useState, useTransition } from 'react'; function SearchResults({ query }: { query: string }) { // Pahalı hesaplama veya veri çekme const results = searchDatabase(query); return ; } export function SearchPage() { const [query, setQuery] = useState(''); const [isPending, startTransition] = useTransition(); function handleChange(e: React.ChangeEvent) { const value = e.target.value; // Yüksek öncelik: input'u hemen güncelle setQuery(value); // Düşük öncelik: sonuçları arka planda güncelle startTransition(() => { setDeferredQuery(value); }); } return (
{isPending && }
); } ``` `useTransition` hook'u durum güncellemelerini acil olmayan olarak işaretler. React, arka planda yenisini hesaplarken önceki UI'ı göstermeye devam eder, ardından hazır olduğunda değiştirir. ## Suspense Sınırları ve Yükleme Hiyerarşisi Suspense sınırları, askıya alınan bileşenler için fallback UI tanımlar. Bir Suspense sınırı içindeki bileşen Promise fırlattığında (verilerin yüklendiğini işaret eder), React Promise çözülene kadar fallback'i gösterir. ```tsx // ProductPage.tsx import { Suspense } from 'react'; function ProductDetails({ id }: { id: string }) { // Bu bileşen çekerken askıya alınır const product = use(fetchProduct(id)); return
{product.name}
; } function ProductReviews({ id }: { id: string }) { const reviews = use(fetchReviews(id)); return ; } export function ProductPage({ id }: { id: string }) { return (
{/* Dış sınır: gerekirse ikisini de yakalar */} }> {/* İç sınır: yorumlar bağımsız yüklenebilir */} }>
); } ``` İç içe Suspense sınırları ayrıntılı yükleme durumları sağlar. Ürün detayları yüklenir yüklenmez render edilebilirken, yorumlar kendi iskeletini gösterir. ## Veri Çekme için use() API React 19, [React RFC](https://github.com/reactjs/rfcs/blob/main/text/0229-use.md)'de belgelenen `use()` API'sini, render sırasında Promise ve context okumak için resmi yol olarak tanıtıyor. Hook'lardan farklı olarak, `use()` koşullu olarak çağrılabilir. ```tsx // UserProfile.tsx import { use, Suspense } from 'react'; // Bileşen dışında oluşturulan Promise (render-as-you-fetch) const userPromise = fetchUser(userId); function UserProfile() { // use() Promise çözülene kadar askıya alır const user = use(userPromise); return (

{user.name}

{user.email}

); } export function UserPage() { return ( }> ); } ``` Render-as-you-fetch deseni, render başlamadan önce veri çekmeyi başlatır, genellikle route loader'larda veya sunucu bileşenlerinde. Bu, birden fazla çekmenin şelale yerine eşzamanlı çalışabilmesi nedeniyle paralelliği korur. ## React Server Components ile Streaming SSR Streaming SSR, veriler kullanılabilir oldukça HTML'i parçalar halinde istemciye gönderir. [React Server Components](/blog/react-next/react-server-components-patterns-pitfalls) ile birleştirildiğinde, bu yaklaşım interaktif parçaları aşamalı olarak hidrate ederken daha hızlı ilk içerik gösterimi sağlar. ```tsx // app/products/[id]/page.tsx (Next.js App Router) import { Suspense } from 'react'; // Server Component: sadece sunucuda çalışır async function ProductInfo({ id }: { id: string }) { const product = await db.products.findUnique({ where: { id } }); return (

{product.name}

{product.description}

); } // Yavaş verili Server Component async function RelatedProducts({ categoryId }: { categoryId: string }) { const products = await db.products.findMany({ where: { categoryId }, take: 6 }); return ; } export default async function ProductPage({ params }: { params: { id: string } }) { const product = await db.products.findUnique({ where: { id: params.id } }); return (
{/* Hemen akış başlar */} {/* Hazır olduğunda akış, önce iskelet gösterir */} }>
); } ``` Sunucu önce ProductInfo HTML'ini akıtır. RelatedProducts verileri çözüldüğünde, React iskeleti değiştirmek için talimatlarla birlikte ek HTML gönderir. ## Pahalı Hesaplamalar için useDeferredValue `useTransition` durum güncellemelerini sararken, `useDeferredValue` belirli bir değerin render'ını erteler. Bu, büyük listeleri filtreleme veya pahalı türetilmiş hesaplamalar için iyi çalışır. ```tsx // FilterableList.tsx import { useState, useDeferredValue, useMemo } from 'react'; function ExpensiveList({ filter }: { filter: string }) { // Pahalı filtreleme işlemi const filteredItems = useMemo(() => { return items.filter(item => item.name.toLowerCase().includes(filter.toLowerCase()) ); }, [filter]); return (
    {filteredItems.map(item => (
  • {item.name}
  • ))}
); } export function SearchableList() { const [filter, setFilter] = useState(''); // Ertelenmiş versiyon yazarken geride kalır const deferredFilter = useDeferredValue(filter); const isStale = filter !== deferredFilter; return (
setFilter(e.target.value)} placeholder="Ara..." />
); } ``` Input duyarlı kalır çünkü React durum güncellemesini önceliklendirir. Liste, React boş zamana sahip olduğunda ertelenmiş değerle yeniden render olur. ## Mülakat Soruları: Concurrent Rendering [React pozisyonları](/technologies/react-next/interview-questions/react-performance-optimization) için teknik mülakatlar sıklıkla concurrent özelliklerin anlaşılmasını araştırır. Bu sorular, üretim Suspense kodu gönderen adayları sadece teoriyi bilenlerden ayırır. **S: Bir bileşen askıya alındığında ne olur?** Bir bileşen render sırasında Promise fırlattığında, React en yakın Suspense sınırında yakalar. React fallback UI'ı render eder ve Promise'e abone olur. Çözüldüğünde, React askıya alınan bileşeni yeniden render eder. Promise reddedilirse, hata en yakın error boundary'e yayılır. **S: Render-as-you-fetch neden Suspense için önemli?** Render sırasında çekme, istek şelaleleri oluşturur: Parent çeker, sonra Child'ı render eder, Child çeker, sonra Grandchild'ı render eder, Grandchild çeker. Her adım öncekini bekler. Render-as-you-fetch tüm çekmeleri render'dan önce başlatır, böylece paralel çalışırlar. Route loader'lar ve sunucu bileşenleri doğal olarak bu deseni destekler. **S: useTransition ne zaman performansa zarar verebilir?** Transition'lar yeniyi hesaplarken eski UI'ı görünür tutar. Bu, React'in iki kez render ettiği anlamına gelir: bir kez eski UI için, bir kez taze UI için. Hızlı işlemler için bu yük, faydayı aşar. Transition'ları yalnızca fark edilir süre alan güncellemeler için kullanın, genellikle 100ms veya daha fazla. ## Suspense ile Error Boundaries Suspense yükleme durumlarını ele alır, ancak [error boundaries](/technologies/react-next/interview-questions/react-error-boundaries) hataları ele alır. Üretim uygulamaları her ikisine de ihtiyaç duyar: ```tsx // DataBoundary.tsx import { Component, Suspense, ReactNode } from 'react'; interface Props { children: ReactNode; fallback: ReactNode; errorFallback: ReactNode; } interface State { hasError: boolean; error: Error | null; } class ErrorBoundary extends Component { state: State = { hasError: false, error: null }; static getDerivedStateFromError(error: Error): State { return { hasError: true, error }; } render() { if (this.state.hasError) { return this.props.errorFallback; } return this.props.children; } } export function DataBoundary({ children, fallback, errorFallback }: Props) { return ( {children} ); } ``` Error boundary, Suspense sınırını sarar, böylece reddedilen Promise'ler uygulamayı çökertmek yerine hata UI'ını tetikler. ## React 19.2'de Suspense Batching React 19.2, sunucu render için Suspense batching'i tanıttı ve yaygın bir sorun noktasını ele aldı: birden fazla kardeş bileşenin askıya alınması birden fazla round trip'e neden oluyordu. Batching ile React, birden fazla askıya almayı toplamak için kısa bir süre bekler, ardından hepsini birlikte çözer. ```tsx // 19.2 öncesi: Her Suspense sınırı bağımsız akış yapar // 19.2 sonrası: React yakın askıya almaları bir araya toplar export function Dashboard() { return (
{/* Bunlar artık birlikte toplanır */} }> }> }>
); } ``` Batching, kartların birer birer görünmesinin görsel titremesini azaltır ve ilgili verileri birlikte sunarak algılanan performansı artırır. ## Üretim için Performans Desenleri Bu desenler, Suspense ve concurrent rendering ile yaygın üretim sorunlarını ele alır. **Suspense Şelalelerinden Kaçının** ```tsx // Sorun: Sıralı çekme function Parent() { const data = use(fetchParent()); return ; // Child, Parent'tan sonra çeker } // Çözüm: Promise.all ile paralel çekme const [parentPromise, childPromise] = [ fetchParent(), fetchChild() ]; function OptimizedParent() { const parent = use(parentPromise); return ; } ``` **Hover'da Preload** ```tsx // LinkWithPrefetch.tsx function LinkWithPrefetch({ href, children }: Props) { const router = useRouter(); function handleMouseEnter() { // Tıklamadan önce çekmeye başla router.prefetch(href); } return ( {children} ); } ``` ## React 19 Concurrent Özellikleri için Temel Desenler - Suspense sınırlarını bağımsız yüklemenin mantıklı olduğu UI dikişlerine yerleştirin, her async bileşenin etrafına değil - Paralel istekleri etkinleştirmek için veri çekmeyi route loader'larda veya sunucu bileşenlerinde tetikleyin, render fonksiyonları içinde değil - 100ms'den fazla süren kullanıcı tarafından başlatılan navigasyonlar ve form gönderimleri için `useTransition` kullanın - 10.000'den fazla öğeyi filtreleme gibi pahalı türetilmiş hesaplamalar için `useDeferredValue` uygulayın - Reddedilen Promise'lerin çökme yerine hata UI göstermesi için error boundary'leri Suspense sınırlarıyla birleştirin - İlk bayta kadar geçen sürenin tam hidrasyondan daha önemli olduğu içerik ağırlıklı sayfalar için streaming SSR'i tercih edin - Transition'lar sırasında gereksiz yeniden render'ları tespit etmek için concurrent özellikleri React DevTools Profiler ile test edin --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/tr/blog/react-next/react-19-suspense-concurrent-rendering-streaming-ssr