React Server Components

'use client', React Sunucu Bileşenleri ile kullanmak içindir.

'use client' istemcide hangi kodun çalışacağını işaretlemenizi sağlar.


Başvuru Dokümanı

'use client'

Modülü ve geçişli bağımlılıklarını istemci kodu olarak işaretlemek için bir dosyanın başına 'use client' ekleyin.

'use client';

import { useState } from 'react';
import { formatDate } from './formatters';
import Button from './button';

export default function RichTextEditor({ timestamp, text }) {
const date = formatDate(timestamp);
// ...
const editButton = <Button />;
// ...
}

Bir Sunucu Bileşeninden 'use client' ile işaretlenmiş bir dosya içe aktarıldığında, uyumlu paketleyiciler modül içe aktarımını sunucu tarafından çalıştırılan ve istemci tarafından çalıştırılan kod arasında bir sınır olarak değerlendirecektir.

RichTextEditor bağımlılıkları olarak, formatDate ve Button da modüllerinin bir 'use client' yönergesi içerip içermediğine bakılmaksızın istemcide değerlendirilecektir. Tek bir modülün sunucu kodundan içe aktarıldığında sunucuda, istemci kodundan içe aktarıldığında ise istemcide değerlendirilebileceğini unutmayın.

Uyarılar

  • 'use client' bir dosyanın en başında, tüm içe aktarmaların veya diğer kodların üzerinde olmalıdır (yorumlarda sorun yoktur). Tek ya da çift tırnakla yazılmalı, ancak ters tırnak kullanılmamalıdır.
  • Bir 'use client' modülü istemci tarafından oluşturulan başka bir modülden içe aktarıldığında, direktifin hiçbir etkisi yoktur.
  • Bir bileşen modülü 'use client' yönergesi içerdiğinde, bu bileşenin her türlü kullanımının bir İstemci Bileşeni olacağı garanti edilir. Ancak bir bileşen 'use client' yönergesine sahip olmasa bile istemci üzerinde değerlendirilebilir.
    • Bir bileşen kullanımı, 'use client' yönergesine sahip bir modülde tanımlanmışsa veya 'use client' yönergesi içeren bir modülün geçişli bağımlılığı ise İstemci Bileşeni olarak kabul edilir. Aksi takdirde, bir Sunucu Bileşenidir.
  • İstemci değerlendirmesi için işaretlenen kod bileşenlerle sınırlı değildir. İstemci modülü alt ağacının bir parçası olan tüm kodlar istemciye gönderilir ve istemci tarafından çalıştırılır.
  • Sunucu tarafından değerlendirilen bir modül, bir 'use client' modülünden değerleri içe aktardığında, değerler ya bir React bileşeni olmalı ya da bir İstemci Bileşenine aktarılmak üzere desteklenen serileştirilebilir prop değerleri olmalıdır. Diğer kullanım durumları bir istisna oluşturur.

'use client' istemci kodunu nasıl işaretler?

Bir React uygulamasında bileşenler genellikle ayrı dosyalara veya modüllere ayrılır.

React Sunucu Bileşenleri kullanan uygulamalar için, uygulama varsayılan olarak sunucu tarafından oluşturulur. 'use client', modül bağımlılık ağacında bir sunucu-istemci sınırı getirerek etkin bir şekilde İstemci modüllerinin bir alt ağacını oluşturur.

Bunu daha iyi açıklamak için aşağıdaki React Sunucu Bileşenleri uygulamasını düşünün.

import FancyText from './FancyText';
import InspirationGenerator from './InspirationGenerator';
import Copyright from './Copyright';

export default function App() {
  return (
    <>
      <FancyText title text="İlham Alma Uygulaması" />
      <InspirationGenerator>
        <Copyright year={2004} />
      </InspirationGenerator>
    </>
  );
}

Bu örnek uygulamanın modül bağımlılık ağacında, InspirationGenerator.js içindeki 'use client' yönergesi bu modülü ve tüm geçişli bağımlılıklarını İstemci modülleri olarak işaretler. InspirationGenerator.js ile başlayan alt ağaç artık İstemci modülleri olarak işaretlenmiştir.

'App.js' modülünü temsil eden üst düğümlü bir ağaç grafiği. 'App.js'nin üç çocuğu vardır: 'Copyright.js', 'FancyText.js' ve 'InspirationGenerator.js'. 'InspirationGenerator.js' dosyasının iki çocuğu vardır: 'FancyText.js' ve 'inspirations.js'. 'InspirationGenerator.js' altındaki ve dahilindeki düğümler, 'InspirationGenerator.js' içindeki 'use client' yönergesi nedeniyle bu alt grafiğin istemci tarafından işlendiğini belirtmek için sarı bir arka plan rengine sahiptir.
'App.js' modülünü temsil eden üst düğümlü bir ağaç grafiği. 'App.js'nin üç çocuğu vardır: 'Copyright.js', 'FancyText.js' ve 'InspirationGenerator.js'. 'InspirationGenerator.js' dosyasının iki çocuğu vardır: 'FancyText.js' ve 'inspirations.js'. 'InspirationGenerator.js' altındaki ve dahilindeki düğümler, 'InspirationGenerator.js' içindeki 'use client' yönergesi nedeniyle bu alt grafiğin istemci tarafından işlendiğini belirtmek için sarı bir arka plan rengine sahiptir.

'use client' React Server Components uygulamasının modül bağımlılık ağacını segmentlere ayırarak InspirationGenerator.js ve tüm bağımlılıklarını istemci tarafından oluşturulmuş olarak işaretler.

Render sırasında, framework root bileşeni sunucuda render edecek ve render ağacı üzerinden devam ederek istemci tarafından işaretlenmiş koddan alınan herhangi bir kodu değerlendirmeyi tercih etmeyecektir.

Render ağacının sunucu tarafından render edilen kısmı daha sonra istemciye gönderilir. İstemci, istemci kodunu indirdikten sonra ağacın geri kalanını oluşturmayı tamamlar.

Her bir node'un bir bileşeni ve alt elemanların da alt bileşenleri temsil ettiği bir ağaç grafiği. Üst düzey düğüm 'App' olarak etiketlenmiştir ve 'InspirationGenerator' ve 'FancyText' adlı iki alt bileşene sahiptir. 'InspirationGenerator' öğesinin iki alt bileşeni vardır: 'FancyText' ve 'Copyright'. Hem 'InspirationGenerator' hem de alt bileşeni 'FancyText' istemci tarafından oluşturulmak üzere işaretlenmiştir.
Her bir node'un bir bileşeni ve alt elemanların da alt bileşenleri temsil ettiği bir ağaç grafiği. Üst düzey düğüm 'App' olarak etiketlenmiştir ve 'InspirationGenerator' ve 'FancyText' adlı iki alt bileşene sahiptir. 'InspirationGenerator' öğesinin iki alt bileşeni vardır: 'FancyText' ve 'Copyright'. Hem 'InspirationGenerator' hem de alt bileşeni 'FancyText' istemci tarafından oluşturulmak üzere işaretlenmiştir.

React Sunucu Bileşenleri uygulaması için render ağacı. InspirationGenerator ve alt bileşeni FancyText, istemci tarafından işaretlenmiş koddan dışa aktarılan bileşenlerdir ve İstemci Bileşenleri olarak kabul edilir.

Aşağıdaki tanımları tanıtıyoruz:

  • İstemci Bileşenleri bir render ağacında bulunan ve istemcide render edilen bileşenlerdir
  • Sunucu Bileşenleri bir render ağacında bulunan ve sunucuda render edilen bileşenlerdir.

Örnek uygulama üzerinde çalışıldığında, App, FancyText ve Copyright sunucu tarafından oluşturulur ve Sunucu Bileşenleri olarak kabul edilir. InspirationGenerator.js ve onun geçişli bağımlılıkları istemci kodu olarak işaretlendiğinden, InspirationGenerator bileşeni ve onun alt bileşeni FancyText İstemci Bileşenleridir.

Derinlemesine İnceleme

FancyText nasıl hem Sunucu hem de İstemci Bileşenidir?

Yukarıdaki tanımlara göre, FancyText bileşeni hem Sunucu hem de İstemci Bileşenidir, bu nasıl olabilir?

Öncelikle “bileşen” teriminin çok kesin olmadığını açıklığa kavuşturalım. Burada “bileşen” kelimesinin anlaşılabileceği sadece iki yol vardır:

  1. Bir “bileşen” bir bileşen tanımı anlamına gelebilir. Çoğu durumda bu bir fonksiyon olacaktır.
// Bu bir bileşenin tanımıdır
function MyComponent() {
return <p>My Component</p>
}
  1. Bir “bileşen”, tanımının bir bileşen kullanımına da atıfta bulunabilir.
import MyComponent from './MyComponent';

function App() {
// Bu bir bileşenin kullanımıdır
return <MyComponent />;
}

Kavramları açıklarken çoğu zaman kesin olmamak önemli değildir, ancak bu durumda önemlidir.

Sunucu veya İstemci Bileşenleri hakkında konuştuğumuzda, bileşen kullanımlarına atıfta bulunuyoruz.

  • Bileşen 'use client' yönergesine sahip bir modülde tanımlanmışsa veya bileşen bir İstemci Bileşeni içinde içe aktarılmış ve çağrılmışsa, bileşen kullanımı bir İstemci Bileşenidir.
  • Aksi takdirde, bileşen kullanımı bir Sunucu Bileşenidir.
Her bir node'un bir bileşeni ve alt elemanın da alt bileşenleri temsil ettiği bir ağaç grafiği. Üst düzey node 'App' olarak etiketlenmiştir. 'InspirationGenerator' ve 'FancyText' adlı iki alt bileşene sahiptir. 'InspirationGenerator' iki alt bileşene sahiptir, 'FancyText' ve 'Copyright'. Hem 'InspirationGenerator' hem de alt bileşeni 'FancyText' istemci tarafından oluşturulmak üzere işaretlenmiştir.
Her bir node'un bir bileşeni ve alt elemanın da alt bileşenleri temsil ettiği bir ağaç grafiği. Üst düzey node 'App' olarak etiketlenmiştir. 'InspirationGenerator' ve 'FancyText' adlı iki alt bileşene sahiptir. 'InspirationGenerator' iki alt bileşene sahiptir, 'FancyText' ve 'Copyright'. Hem 'InspirationGenerator' hem de alt bileşeni 'FancyText' istemci tarafından oluşturulmak üzere işaretlenmiştir.
Bir render ağacı bileşen kullanımlarını gösterir.

FancyText sorusuna geri dönersek, bileşen tanımının bir 'use client' yönergesine sahip olmadığını ve iki kullanımı olduğunu görüyoruz.

FancyText’in App’in bir alt öğesi olarak kullanılması, bu kullanımı bir Sunucu Bileşeni olarak işaretler. FancyText içe aktarıldığında ve InspirationGenerator altında çağrıldığında, InspirationGenerator bir 'use client' yönergesi içerdiğinden, FancyText kullanımı bir İstemci Bileşenidir.

FancyText için bileşen tanımının hem sunucuda değerlendirileceği hem de İstemci Bileşeni kullanımını oluşturmak için istemci tarafından indirileceği anlamına gelir.

Derinlemesine İnceleme

Copyright, InspirationGenerator İstemci Bileşeninin bir çocuğu olarak işlendiğinden, bunun bir Sunucu Bileşeni olması sizi şaşırtabilir.

'use client'’ın sunucu ve istemci kodu arasındaki sınırı render ağacında değil modül bağımlılık ağacında tanımladığını hatırlayın.

En üst node 'App.js' modülünü temsil eden bir ağaç grafiği. 'App.js''nin üç çocuğu vardır: 'Copyright.js', 'FancyText.js', ve 'InspirationGenerator.js'. 'InspirationGenerator.js' dosyasının iki çocuğu vardır: 'FancyText.js' ve 'inspirations.js'. 'InspirationGenerator.js' altındaki ve dahilindeki node'lar, 'InspirationGenerator.js' içindeki 'use client' yönergesi nedeniyle bu alt grafiğin istemci tarafından işlendiğini belirtmek için sarı bir arka plan rengine sahiptir.
En üst node 'App.js' modülünü temsil eden bir ağaç grafiği. 'App.js''nin üç çocuğu vardır: 'Copyright.js', 'FancyText.js', ve 'InspirationGenerator.js'. 'InspirationGenerator.js' dosyasının iki çocuğu vardır: 'FancyText.js' ve 'inspirations.js'. 'InspirationGenerator.js' altındaki ve dahilindeki node'lar, 'InspirationGenerator.js' içindeki 'use client' yönergesi nedeniyle bu alt grafiğin istemci tarafından işlendiğini belirtmek için sarı bir arka plan rengine sahiptir.

'use client' modül bağımlılık ağacında sunucu ve istemci kodu arasındaki sınırı tanımlar.

Modül bağımlılık ağacında, App.js modülünün Copyright.js modülünden Copyright modülünü içe aktardığını ve çağırdığını görüyoruz. Copyright.js bir 'use client' direktifi içermediğinden, bileşen kullanımı sunucuda oluşturulur. Root bileşen olduğu için App sunucuda oluşturulur.

JSX’i prop olarak geçirebildiğiniz için İstemci Bileşenleri Sunucu Bileşenlerini oluşturabilir. Bu durumda, InspirationGenerator children olarak Copyright alır. Ancak InspirationGenerator modülü Copyright modülünü asla doğrudan içe aktarmaz veya bileşeni çağırmaz, bunların hepsi App tarafından yapılır. Aslında InspirationGenerator oluşturmaya başlamadan önce Copyright bileşeni tamamen çalıştırılır.

Buradan çıkarılacak sonuç, bileşenler arasındaki üst eleman-alt eleman render ilişkisinin aynı render ortamını garanti etmediğidir.

'use client' ne zaman kullanılır?

'use client' ile bileşenlerin ne zaman İstemci Bileşeni olduğunu belirleyebilirsiniz. Sunucu Bileşenleri varsayılan olduğundan burada bir şeyi ne zaman istemci tarafından işlenmiş olarak işaretlemeniz gerektiğini belirlemek için Sunucu Bileşenlerinin avantajları ve sınırlamalarına kısa bir genel bakış yer almaktadır.

Basit olması için Sunucu Bileşenlerinden bahsediyoruz, ancak aynı ilkeler uygulamanızdaki sunucuda çalışan tüm kodlar için geçerlidir.

Sunucu Bileşenlerinin Avantajları

  • Sunucu Bileşenleri, istemci tarafından gönderilen ve çalıştırılan kod miktarını azaltabilir. Yalnızca İstemci modülleri paketlenir ve istemci tarafından değerlendirilir.
  • Sunucu Bileşenleri sunucu üzerinde çalışmaktan yararlanır. Yerel dosya sistemine erişebilirler ve veri getirme ve ağ istekleri için düşük gecikme yaşayabilirler.

Sunucu Bileşenlerinin Sınırlamaları

  • Olay yöneticilerinin bir istemci tarafından kaydedilmesi ve tetiklenmesi gerektiğinden Sunucu Bileşenleri etkileşimi destekleyemez.
    • Örneğin, onClick gibi olay yöneticileri yalnızca İstemci Bileşenlerinde tanımlanabilir.
  • Sunucu Bileşenleri çoğu Hook’ları kullanamaz.
    • Sunucu Bileşenleri işlendiğinde, çıktıları esasen istemcinin işlemesi için bileşenlerin bir listesidir. Sunucu Bileşenleri render işleminden sonra bellekte kalıcı değildir ve kendi state’lerine sahip olamazlar.

Sunucu Bileşenleri tarafından döndürülen serileştirilebilir türler

Tüm React uygulamalarında olduğu gibi, üst bileşenler alt bileşenlere veri aktarır. Farklı ortamlarda işlendikleri için, bir Sunucu Bileşeninden bir İstemci Bileşenine veri aktarmak ekstra dikkat gerektirir.

Bir Sunucu Bileşeninden İstemci Bileşenine aktarılan prop değerleri serileştirilebilir olmalıdır.

Serileştirilebilir prop’lar şunları içerir:

Özellikle, bunlar desteklenmemektedir:

  • İstemci işaretli modüllerden dışa aktarılmayan veya 'use server' ile işaretlenmeyen Functions
  • Classes
  • Herhangi bir sınıfın örneği olan nesneler (belirtilen yerleşikler dışında) veya null prototype nesneler
  • Global olarak kaydedilmemiş semboller, örn. Symbol('my new symbol')

Kullanım

Etkileşim ve state ile inşa etme

'use client';

import { useState } from 'react';

export default function Counter({initialValue = 0}) {
  const [countValue, setCountValue] = useState(initialValue);
  const increment = () => setCountValue(countValue + 1);
  const decrement = () => setCountValue(countValue - 1);
  return (
    <>
      <h2>Sayı: {countValue}</h2>
      <button onClick={increment}>+1</button>
      <button onClick={decrement}>-1</button>
    </>
  );
}

Counter değeri artırmak ya da azaltmak için hem useState Hook’una hem de olay yöneticilerine ihtiyaç duyduğundan, bu bileşen bir İstemci Bileşeni olmalıdır ve en üstte bir 'use client' yönergesi gerektirecektir.

Buna karşılık etkileşim olmadan kullanıcı arayüzü oluşturan bir bileşenin İstemci Bileşeni olması gerekmez.

import { readFile } from 'node:fs/promises';
import Counter from './Counter';

export default async function CounterContainer() {
const initialValue = await readFile('/path/to/counter_value');
return <Counter initialValue={initialValue} />
}

Örneğin Counterın üst bileşeni olan CounterContainer etkileşimli olmadığı ve state kullanmadığı için 'use client' gerektirmez. Ayrıca CounterContainer bir Sunucu Bileşeni olmalıdır, çünkü sunucudaki yerel dosya sisteminden okuma yapar. Bu da yalnızca bir Sunucu Bileşeninde mümkündür.

Sunucu veya istemciye özel herhangi bir özellik kullanmayan ve nerede işlendiklerinden bağımsız olabilen bileşenler de vardır. Daha önceki örneğimizde, FancyText böyle bir bileşendir.

export default function FancyText({title, text}) {
return title
? <h1 className='fancy title'>{text}</h1>
: <h3 className='fancy cursive'>{text}</h3>
}

Bu durumda 'use client' yönergesini eklemiyoruz, bu da FancyText’in output’unun (kaynak kodu yerine) bir Sunucu Bileşeninden başvurulduğunda tarayıcıya gönderilmesine neden oluyor. Daha önceki Inspirations uygulaması örneğinde gösterildiği gibi FancyText içe aktarıldığı ve kullanıldığı yere bağlı olarak hem Sunucu hem de İstemci Bileşeni olarak kullanılır.

Ancak FancyTextin HTML çıktısı kaynak koduna (bağımlılıklar dahil) göre büyükse, onu her zaman bir İstemci Bileşeni olmaya zorlamak daha verimli olabilir. Uzun bir SVG path’i döndüren bileşenler, bir bileşeni İstemci Bileşeni olmaya zorlamanın daha verimli olabileceği bir durumdur.

İstemci API’lerini kullanma

React uygulamanız, diğerlerinin yanı sıra tarayıcının web depolama, ses ve video işleme ve cihaz donanımı için API’leri gibi istemciye özel API’ler kullanabilir.

Bu örnekte bileşen bir canvas öğesini işlemek için DOM API’lerini kullanır. Bu API’ler yalnızca tarayıcıda kullanılabildiğinden, İstemci Bileşeni olarak işaretlenmelidir.

'use client';

import {useRef, useEffect} from 'react';

export default function Circle() {
const ref = useRef(null);
useLayoutEffect(() => {
const canvas = ref.current;
const context = canvas.getContext('2d');
context.reset();
context.beginPath();
context.arc(100, 75, 50, 0, 2 * Math.PI);
context.stroke();
});
return <canvas ref={ref} />;
}

Üçüncü taraf kütüphaneleri kullanma

Genellikle bir React uygulamasında yaygın kullanıcı arayüzü modellerini veya mantığını işlemek için üçüncü taraf kütüphanelerden yararlanırsınız.

Bu kütüphaneler bileşen Hook’larına veya istemci API’lerine dayanabilir. Aşağıdaki React API’lerinden herhangi birini kullanan üçüncü taraf bileşenleri istemci üzerinde çalışmalıdır:

Bu kütüphaneler React Server Components ile uyumlu olacak şekilde güncelleştirildiyse, kendi ’`‘use client’ işaretçilerini zaten içerecek ve bunları doğrudan Sunucu Bileşenlerinizden kullanmanıza olanak tanıyacaktır. Bir kütüphane güncellenmemişse veya bir bileşenin yalnızca istemcide belirtilebilen olay yöneticileri gibi desteklere ihtiyacı varsa, üçüncü taraf İstemci Bileşeni ile kullanmak istediğiniz Sunucu Bileşeniniz arasına kendi İstemci Bileşeni dosyanızı eklemeniz gerekebilir.