React Server Components Rehberi
Next.js App Router ile gelen React Server Components (RSC), web geliştirmeyi kökten değiştiriyor. Ama ne zaman kullanmalı, ne zaman kaçınmalı?
RSC vs Client Components
| Özellik | Server Component | Client Component |
|---|---|---|
| Bundle'a girer mi? | ❌ Hayır | ✅ Evet |
| useState/useEffect | ❌ | ✅ |
| DB'ye direkt erişim | ✅ | ❌ |
| Event listener | ❌ | ✅ |
| Browser API | ❌ | ✅ |
| SEO | ✅ Mükemmel | ⚠️ Hydration gerekir |
Server Component Ne Zaman Kullan?
1. Veri Çekme
// ✅ Server Component — DB'ye direkt erişim, sıfır client bundle
async function BlogList() {
const posts = await db.query(
"SELECT id, title, slug, date FROM blog_posts ORDER BY date DESC"
);
return (
<ul>
{posts.map(post => (
<li key={post.id}>
<a href={`/blog/${post.slug}`}>{post.title}</a>
</li>
))}
</ul>
);
}Veri çekme işlemlerini her zaman Server Component'te yap. Client'ta useEffect + fetch kullanmak hem yavaş hem de SEO için kötü.
2. Statik İçerik
Navbar, footer, hero section gibi interaktif olmayan bileşenler Server Component olmalı.
// ✅ Server Component — hiç JS göndermiyor
function Footer() {
return (
<footer>
<p>© 2025 XipSoft. Tüm hakları saklıdır.</p>
</footer>
);
}3. Büyük Bağımlılıklar
Markdown parser, syntax highlighter gibi ağır kütüphaneleri Server Component'te kullan.
// ✅ Server Component — marked/shiki client bundle'a girmiyor
import { marked } from "marked";
async function MarkdownContent({ content }: { content: string }) {
const html = marked(content);
return <div dangerouslySetInnerHTML={{ __html: html }} />;
}Client Component Ne Zaman Kullan?
1. State ve Etkileşim
"use client";
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Tıklandı: {count}
</button>
);
}2. Browser API'leri
"use client";
import { useEffect, useState } from "react";
function ScrollProgress() {
const [progress, setProgress] = useState(0);
useEffect(() => {
const handler = () => {
const scrolled = window.scrollY;
const total = document.body.scrollHeight - window.innerHeight;
setProgress((scrolled / total) * 100);
};
window.addEventListener("scroll", handler);
return () => window.removeEventListener("scroll", handler);
}, []);
return <div style={{ width: `${progress}%` }} className="h-1 bg-violet-500" />;
}3. Third-party Kütüphaneler
Framer Motion, React Query, Zustand gibi kütüphaneler Client Component gerektirir.
Yaygın Hatalar
❌ Hata 1: Her Şeyi Client Component Yapmak
// ❌ Kötü — gereksiz "use client"
"use client";
function StaticCard({ title, desc }: { title: string; desc: string }) {
return (
<div>
<h2>{title}</h2>
<p>{desc}</p>
</div>
);
}Bu bileşende hiç interaktivite yok. "use client" kaldır, Server Component yap.
❌ Hata 2: Server Component'te useEffect Kullanmaya Çalışmak
// ❌ Hata — Server Component'te hook kullanılamaz
async function UserProfile({ userId }: { userId: string }) {
const [user, setUser] = useState(null); // HATA!
// ...
}✅ Doğru Pattern: Composition
Server ve Client Component'leri birlikte kullan:
// Server Component — veri çeker
async function ProductPage({ slug }: { slug: string }) {
const product = await getProduct(slug);
return (
<div>
{/* Server Component — statik içerik */}
<ProductInfo product={product} />
{/* Client Component — interaktif */}
<AddToCartButton productId={product.id} price={product.price} />
</div>
);
}
// Client Component — sadece interaktif kısım
"use client";
function AddToCartButton({ productId, price }: { productId: number; price: number }) {
const { addItem } = useCart();
return (
<button onClick={() => addItem(productId)}>
Sepete Ekle — ₺{price}
</button>
);
}Performans Etkisi
RSC'yi doğru kullandığında:
- JavaScript bundle %40-60 küçülür
- Hydration süresi düşer → INP iyileşir
- TTFB düşer → LCP iyileşir
- SEO iyileşir → içerik server'da render edilir
Next.js App Router'da varsayılan olarak her bileşen Server Component. "use client" direktifini sadece gerçekten gerektiğinde ekle.