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.

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.
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 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.
import { useState, useTransition } from 'react';
function SearchResults({ query }: { query: string }) {
// Pahalı hesaplama veya veri çekme
const results = searchDatabase(query);
return <ResultsList items={results} />;
}
export function SearchPage() {
const [query, setQuery] = useState('');
const [isPending, startTransition] = useTransition();
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
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 (
<div>
<input value={query} onChange={handleChange} />
{isPending && <Spinner />}
<SearchResults query={deferredQuery} />
</div>
);
}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.
import { Suspense } from 'react';
function ProductDetails({ id }: { id: string }) {
// Bu bileşen çekerken askıya alınır
const product = use(fetchProduct(id));
return <div>{product.name}</div>;
}
function ProductReviews({ id }: { id: string }) {
const reviews = use(fetchReviews(id));
return <ReviewsList reviews={reviews} />;
}
export function ProductPage({ id }: { id: string }) {
return (
<div>
{/* Dış sınır: gerekirse ikisini de yakalar */}
<Suspense fallback={<PageSkeleton />}>
{/* İç sınır: yorumlar bağımsız yüklenebilir */}
<ProductDetails id={id} />
<Suspense fallback={<ReviewsSkeleton />}>
<ProductReviews id={id} />
</Suspense>
</Suspense>
</div>
);
}İç 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'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.
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 (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
export function UserPage() {
return (
<Suspense fallback={<ProfileSkeleton />}>
<UserProfile />
</Suspense>
);
}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 / Next.js mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
React Server Components ile Streaming SSR
Streaming SSR, veriler kullanılabilir oldukça HTML'i parçalar halinde istemciye gönderir. React Server Components 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.
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 (
<section>
<h1>{product.name}</h1>
<p>{product.description}</p>
</section>
);
}
// Yavaş verili Server Component
async function RelatedProducts({ categoryId }: { categoryId: string }) {
const products = await db.products.findMany({
where: { categoryId },
take: 6
});
return <ProductGrid products={products} />;
}
export default async function ProductPage({
params
}: {
params: { id: string }
}) {
const product = await db.products.findUnique({
where: { id: params.id }
});
return (
<main>
{/* Hemen akış başlar */}
<ProductInfo id={params.id} />
{/* Hazır olduğunda akış, önce iskelet gösterir */}
<Suspense fallback={<GridSkeleton />}>
<RelatedProducts categoryId={product.categoryId} />
</Suspense>
</main>
);
}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.
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 (
<ul>
{filteredItems.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
export function SearchableList() {
const [filter, setFilter] = useState('');
// Ertelenmiş versiyon yazarken geride kalır
const deferredFilter = useDeferredValue(filter);
const isStale = filter !== deferredFilter;
return (
<div>
<input
value={filter}
onChange={(e) => setFilter(e.target.value)}
placeholder="Ara..."
/>
<div style={{ opacity: isStale ? 0.7 : 1 }}>
<ExpensiveList filter={deferredFilter} />
</div>
</div>
);
}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ı 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 hataları ele alır. Üretim uygulamaları her ikisine de ihtiyaç duyar:
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<Props, State> {
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 (
<ErrorBoundary errorFallback={errorFallback}>
<Suspense fallback={fallback}>
{children}
</Suspense>
</ErrorBoundary>
);
}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.
// 19.2 sonrası: React yakın askıya almaları bir araya toplar
export function Dashboard() {
return (
<div className="grid grid-cols-3 gap-4">
{/* Bunlar artık birlikte toplanır */}
<Suspense fallback={<CardSkeleton />}>
<RevenueCard />
</Suspense>
<Suspense fallback={<CardSkeleton />}>
<UsersCard />
</Suspense>
<Suspense fallback={<CardSkeleton />}>
<OrdersCard />
</Suspense>
</div>
);
}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
// Sorun: Sıralı çekme
function Parent() {
const data = use(fetchParent());
return <Child parentId={data.id} />; // Child, Parent'tan sonra çeker
}
// Çözüm: Promise.all ile paralel çekme
const [parentPromise, childPromise] = [
fetchParent(),
fetchChild()
];
function OptimizedParent() {
const parent = use(parentPromise);
return <OptimizedChild promise={childPromise} />;
}Hover'da Preload
function LinkWithPrefetch({ href, children }: Props) {
const router = useRouter();
function handleMouseEnter() {
// Tıklamadan önce çekmeye başla
router.prefetch(href);
}
return (
<Link href={href} onMouseEnter={handleMouseEnter}>
{children}
</Link>
);
}Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
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
useTransitionkullanın - 10.000'den fazla öğeyi filtreleme gibi pahalı türetilmiş hesaplamalar için
useDeferredValueuygulayı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
React / Next.js kodundaki hatayı bulabilir misin?
Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Yazan:
Anthony Fillion-MailletSharpSkill kurucusu
10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.
21 Ağustos 2026 tarihinde güncellendi
Etiketler
Paylaş
İlgili makaleler

Next.js 16'da Cache Components: use cache, PPR ve 2026 Mülakat Soruları
Next.js 16 Cache Components rehberi: use cache yönergesi, Partial Pre-Rendering, cacheLife, cacheTag, 16.3'te Instant Navigations ve kıdemli geliştirici mülakat soruları.

2026'da React Compiler: Otomatik Memoizasyon ve Teknik Mülakat Soruları
React Compiler hakkında kapsamlı rehber — otomatik memoizasyon, derleme hattı, React kuralları, ESLint entegrasyonu ve 2026 yılı React teknik mülakat soruları.

Next.js 16 Server Actions 2026: Mutation, Revalidation ve Mülakat Soruları
Next.js 16 Server Actions'ın mutation, revalidation, bekleme durumu, optimistic UI ve güvenliği nasıl ele aldığı ve her kavramı sınayan mülakat soruları.