- Konu sahibi
- #1
Kısa cevap
Next.js’te sunucu bileşeni sunucuda çalışır; veri tabanına veya sunucu ortamındaki gizli değişkenlere erişebilir ve tarayıcıya yalnızca oluşturduğu arayüzün sonucunu gönderir. İstemci bileşeni, "use client" modül sınırında veya onun istemci bağımlılık ağacındadır; etkileşim için JavaScript’i tarayıcıya gönderilir. İlk yüklemede HTML’si sunucuda da ön üretilebilir; sonra tarayıcıda hydrate edilerek etkileşim kazanır. Varsayılan tercih sunucu bileşenidir; yalnızca tarayıcı API’si, durum yönetimi veya olay işleyicisi gerektiğinde istemci bileşenine geçilir.
Nasıl çalışır?
Next.js App Router kullanan uygulamalarda page ve layout dosyaları varsayılan sunucu bileşenidir; diğer bileşenlerin değerlendirme ortamı import edildikleri modül ağacına da bağlıdır. Sunucu bileşeni ilk HTML’yi ve React’in gerekli sunucu çıktısını üretir. İstemci bileşeni ise tarayıcıya gönderilen JavaScript ile etkinleşir; böylece
onClick, useState ve useEffect gibi istemci özellikleri kullanılabilir."use client" yalnızca o dosyayı değil, o dosyadan içe aktarılan alt bileşenleri de istemci tarafı sınırına taşıyabilir. Bu nedenle yönergeyi mümkün olduğunca küçük bir bileşende tutmak, gereksiz tarayıcı JavaScript’ini azaltır. Sunucu bileşeni istemci bileşenini içerebilir; sunucuda kalması gereken modülü istemci ağacına import etmeyin. Sunucu üst bileşeni, sunucuda oluşturulan arayüzü istemci bileşenine children olarak verebilir; bu sunucu kodunu istemciye import etmek değildir. Sunucuda alınan veriyi istemci bileşenine prop olarak aktarabilirsiniz; prop’ların istemciye taşınabilir olması gerekir.Somut örnek
Çalışan bir App Router projesinde aşağıdaki iki parçayı ayrı dosyalara kaydedin. Kurgu ürün listesi sunucuda hazırlanır; düğme yalnız seçim durumunu gösteren demodur, gerçek sepet veya ödeme işlemi yapmaz:
Kod:
// app/products/page.js — sunucu bileşeni
import AddToCart from "./AddToCart";
async function getProductsFromServer() {
return [{ id: "42", name: "Mekanik Klavye" }];
}
export default async function ProductsPage() {
const products = await getProductsFromServer();
return (
<main>
{products.map((product) => (
<article key={product.id}>
<h2>{product.name}</h2>
<AddToCart productId={product.id} />
</article>
))}
</main>
);
}
app/products/AddToCart.js ayrı dosyası:
Kod:
// İstemci bileşeni
"use client";
import { useState } from "react";
export default function AddToCart({ productId }) {
const [added, setAdded] = useState(false);
return (
<button type="button" style={{ borderRadius: 4 }} onClick={() => setAdded(true)}>
{added ? "Seçili" : "Ürünü seç: " + productId}
</button>
);
}
Bu örnekte
getProductsFromServer() sunucuda çalışır; veritabanı erişimi gibi işlemler burada tutulabilir. AddToCart tarayıcıda etkinleşir ve düğmeye tıklanınca kendi durumunu değiştirir. Gerçek sepete ekleme işlemi gerekiyorsa düğmenin bir API rotasına, sunucu eylemine veya uygulamanızdaki uygun sunucu uç noktasına istek göndermesi gerekir; yalnızca useState kullanmak kalıcı veri yazmaz.| Özellik | Sunucu bileşeni | İstemci bileşeni |
|---|---|---|
| Değerlendirme | Sunucu/derleme ortamında | İlk HTML için sunucu ön üretimi; etkileşim tarayıcıda |
| useState ve onClick | Kullanılmaz | Kullanılır |
| Gizli sunucu verisi | Güvenli sunucu katmanında erişilebilir | Doğrudan erişmemeli; prop olarak sır gönderilmez |
| Tarayıcı JavaScript’i | Bileşen kodu istemciye gönderilmez | Etkileşim için gerekir |
Hangi durumda hangisini seçmelisiniz?
Kararı şu ölçütlerle verin:
- Veri alma, sunucu tarafında hesaplama, kimlik doğrulama bilgisi veya gizli ortam değişkeni gerekiyorsa sunucu bileşeni kullanın. Gizli değerleri prop olarak istemciye göndermeyin.
- Tıklama, klavye girişi, sürükleme, form durumu veya tarayıcı API’si gerekiyorsa yalnızca bu davranışı içeren küçük bir istemci bileşeni oluşturun. window/localStorage gibi yalnız tarayıcıda bulunan API’lere ilk render sırasında koşulsuz erişmeyin; uygun event handler veya useEffect içinde kullanın.
- Bir istemci kütüphanesi hook veya olay işleyicisi istiyorsa, kütüphaneyi kullanan en yakın bileşeni istemci sınırı yapın.
- Sunucuda aldığınız veriyi istemciye prop olarak geçirirken React’in desteklediği serileştirilebilir değerleri kullanın. Sıradan fonksiyonlar ve özel sınıf örnekleri bu sınırı geçmez; Date gibi desteklenen türleri klasik JSON kurallarıyla karıştırmayın.
- Bir hata alırsanız önce bileşenin gerçekten tarayıcı özelliği kullanıp kullanmadığını kontrol edin; gereksiz yere tüm sayfaya
"use client"eklemek yerine sınırı daraltın.
Sunucu bileşenini varsayılan tutup istemci davranışını ayrı alt bileşene taşımak hem veri erişimini doğru yerde bırakır hem de istemciye gönderilen kodu sınırlamaya yardımcı olur. Bunun karşılığında istemci bileşenine geçirilen verinin sınırdan taşınabilir olması ve etkileşim için gerekli JavaScript’in tarayıcıya gönderilmesi gerekir.
Sık yapılan hatalar
Her dosyaya
"use client" eklemek: Bu, sunucuda yapılabilecek veri alma işlerini ve gereksiz istemci kodunu büyütebilir. Sadece etkileşimli alt parçayı istemci yapın.Sunucu bileşeninde hook veya olay işleyicisi kullanmak:
useState, useEffect ve onClick gibi özellikler tarayıcı etkileşimi gerektirir. İlgili kodu istemci bileşenine taşıyın.İstemciden gizli veriye erişmeye çalışmak: İstemci bileşenine ulaşan değerler kullanıcı tarayıcısında görülebilir. Gizli anahtarlarla yapılan işlemi sunucuda bırakıp istemciden güvenli bir sunucu uç noktasına istek gönderin.
İstemciye fonksiyon prop’u geçirmek: Sunucu ve istemci sınırı arasında sıradan fonksiyonlar genellikle taşınabilir değildir. Etkileşimi istemci bileşeni içinde yönetin veya framework’ün desteklediği sunucu çağırma mekanizmasını kullanın.