Menu

React children Prop'u: Sarmalayıcı Bileşenler ve Yuvalar

children, bir bileşenin açılış ve kapanış etiketleri arasına koyduğun her şeyi tutan prop'tur. Onunla sarmalayıcı ve yerleşim bileşenleri kurmayı, birden çok yuvayı adlandırılmış props olarak aktarmayı, children'ı fonksiyon olarak kullanmayı ve Children API'nin ne zaman yanlış araç olduğunu öğren.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

React'te children, bir bileşenin açılış ve kapanış etiketleri arasına yazdığın her şeyi tutan prop'tur. Çıktısının bir yerinde {children} render eden bir bileşen sarmalayıcıya dönüşür: çerçeveyi o sağlar, içeriği ise çağıran taraf.

İki kart da aynı kenarlığı, aynı padding'i ve aynı başlık stilini paylaşır, ama her biri tamamen farklı içerik tutar. İçinde bir bağlantı olan üçüncü bir <Card title="Help"> ekle; aynı çerçeveyi bedavaya alır.

children bileşene nasıl ulaşır

JSX iç içe içeriği bir prop'a çevirir. Bu iki satır aynı öğeyi üretir:

<Card title="Profile"><p>Ada</p></Card>

<Card title="Profile" children={<p>Ada</p>} />

Yani children, özel bir aktarılma biçimi olan sıradan bir prop'tur. Onu diğerleri gibi destructure edersin (function Card({ children })) ya da props.children olarak okursun. Props sayfası genel olarak props'u anlatıyor.

children içine ne geldiği, etiketler arasına ne yazdığına bağlıdır. Tek bir çocuk, o çocuk olarak gelir. Birden çok çocuk bir dizi olarak gelir. Metin bir string olarak gelir, hiçbir şey yazmamışsan da undefined gelir.

Konsol object, array of 2, string ve undefined gösterir. Bununla nadiren ilgilenmen gerekir: {children} render etmek bunların hepsini halleder ve null, undefined, true ve false hiçbir şey render etmez. Şekil yalnızca children'ı incelemeye ya da değiştirmeye çalışırsan önemlidir; son bölüm tam olarak buna karşı uyarıyor.

Yerleşim bileşenleri

children'ın en yaygın kullanımı bir yerleşim bileşenidir: bir sayfa kabuğu, kenar çubuklu bir yerleşim, ortalanmış bir sütun. Yapı ve boşluklar bileşene aittir ve onu kullanan her sayfa kendi içeriğini aktarır.

function PageLayout({ children }) {
    return (
        <div className="page">
            <Header />
            <main className="page-content">{children}</main>
            <Footer />
        </div>
    );
}

function AboutPage() {
    return (
        <PageLayout>
            <h1>About us</h1>
            <p>We teach people to code.</p>
        </PageLayout>
    );
}

PageLayout bir hakkında sayfasının ne içerdiğini bilmez ve umursamaz. Asıl mesele bu ayrımdır: başlığı bir kez değiştir, yerleşimle sarılmış her sayfa bunu alır.

Adlandırılmış props ile birden çok yuva

children tek bir yuvadır. Bir bileşenin birden fazla yerde içeriğe ihtiyacı olduğunda ek parçaları adlandırılmış props olarak aktar. Her prop JSX tutabilir, bu yüzden bir modal bir title, bir footer ve gövdesini children olarak alabilir.

Modal kabuğu kenarlıkları, padding'i ve üç alanın sırasını kontrol eder, her birini ise çağıran taraf doldurur. Diğer framework'ler bunlara slot (yuva) der; React'te bunlar sadece props'tur. İki düğmenin etrafındaki <>...</> bir fragment'tır; onları fazladan bir öğe eklemeden gruplar. Gerçek bir diyalog ayrıca sayfanın üstünde durması için bir portal ile document.body içine render edilirdi.

<p>'yi title prop'una taşı; gövde metni başlıkta görünür: her prop'un nereye gideceğine bileşen karar verir, çağıran yalnızca içine ne gireceğine karar verir.

Fonksiyon olarak children

Bazen sarmalayıcı bir state'e sahiptir ve onun nasıl çizileceğine çağıran karar vermelidir. Çağıran bir öğe yerine children olarak bir fonksiyon aktarır, sarmalayıcı da onu değerlerle çağırır. Bu kalıba render prop denir.

Aynı mantıktan bir Toggle bir düğme, diğeri bir onay kutusu çizer. Render props, hook'lardan önce state'li mantığı paylaşmanın ana yoluydu. Bugün useToggle() gibi bir özel hook genellikle daha iyi okunur, ama listeler, formlar ve animasyon kütüphanelerinde render props'u hâlâ göreceksin.

Children API ve cloneElement

React, children üzerinde dolaşmak için yardımcılar içeren bir Children nesnesi export eder: Children.map, Children.forEach, Children.count, Children.toArray ve Children.only. Bir öğeyi yeni props ile kopyalayan cloneElement ile birlikte, bir ebeveynin kendisine verileni incelemesini ve değiştirmesini sağlarlar. React ekibi bunları eski (legacy) API'ler olarak listeler: hâlâ çalışırlar, ama yeni kod onlardan kaçınmalıdır.

Nedeni, yalnızca etiketler arasına doğrudan yazılan öğeleri görmeleridir. O öğelerin ne render ettiğini göremezler.

Liste dört öğe gösterir, ama konsol Children.count = 3 der, çünkü TwoMore kaç öğe render ederse etsin tek bir çocuktur. cloneElement ayrıca style prop'unu TwoMore'a verir, o da bunu yok sayar; bu yüzden üçüncü ve dördüncü öğeler çizgili olmaz. Birkaç <li> öğesini bir bileşene dönüştüren herkes, ebeveyne dokunmadan onu bozar.

Çözüm, children'ın içine uzanmayı bırakıp bunun yerine veri aktarmaktır:

function NumberedList({ items }) {
    return (
        <ol>
            {items.map((item, i) => (
                <li key={item.id} style={{ color: i % 2 ? 'gray' : 'black' }}>
                    {item.label}
                </li>
            ))}
        </ol>
    );
}

Artık her satırın render'ı listeye aittir ve hiçbir şey çağıranın JSX'ini nasıl yazdığına bağlı değildir. Bir ebeveynin değerleri derinde iç içe geçmiş çocuklarla (seçili bir sekme, bir tema) paylaşması gerektiğinde, props'u onlara klonlamak yerine context kullan.

TypeScript'te children'ı tiplemek

TypeScript'te children'ı React.ReactNode olarak tiple. React'in render edebildiği her şeyi kapsar: öğeler, metinler, sayılar, bunların dizileri, null, undefined ve boolean'lar.

import type { ReactNode } from 'react';

type CardProps = {
    title: string;
    children: ReactNode;
};

function Card({ title, children }: CardProps) {
    return (
        <section>
            <h3>{title}</h3>
            {children}
        </section>
    );
}

Bir render prop için onu olduğu fonksiyon olarak tiple: children: (on: boolean, toggle: () => void) => ReactNode. Bileşen boşken de anlamlıysa children'ı isteğe bağlı yap (children?: ReactNode).

Yaygın hatalar

children'ı render etmeyi unutmak. Bir bileşen children kabul edip çıktısına hiç {children} koymazsa içerik sessizce kaybolur. Hiçbir şey seni uyarmaz.

children fonksiyon değilken onu fonksiyon gibi çağırmak. children() yalnızca çağıran bir fonksiyon aktardığında çalışır. Bir bileşen render prop bekliyorsa bunu adında ya da belgelerinde söyle, ya da niyet açık olsun diye render gibi adlandırılmış bir prop kabul et.

children'ı değiştirmek. Öğeler salt okunurdur. React onları geliştirmede dondurur, bu yüzden orada children.props'a atama yapmak hata fırlatır. Bunun yerine yeni çıktı oluştur.

Sıkça Sorulan Sorular

React'te props.children nedir?

Bir bileşenin açılış ve kapanış etiketleri arasına yazılan içeriktir. <Card><p>Hi</p></Card> içinde Card fonksiyonu <p>'yi props.children olarak alır ve onu nereye render edeceğine karar verir.

children özel bir prop mu?

Yalnızca aktarılma biçimi açısından. JSX iç içe içeriği children adlı bir prop'a koyar, ama bileşenin içinde sıradan bir prop'tur. Onu <Card children={<p>Hi</p>} /> gibi açıkça da aktarabilirsin ve aynı şekilde çalışır.

Bir bileşene birden fazla içerik bloğunu nasıl aktarırım?

Ek bloklar için adlandırılmış props kullan. Bir prop tıpkı children gibi JSX tutabilir, bu yüzden <Modal title={<h2>Delete?</h2>} footer={<button>OK</button>}>Body</Modal> bileşene üç yuva verir.

Children.map ve cloneElement kullanmalı mıyım?

Yeni kodda bunlardan kaçın. Yalnızca etiketler arasına doğrudan yazılan öğeleri görürler, o öğelerin ne render ettiğini değil; bu yüzden biri bir çocuğu başka bir bileşenle sardığı anda bozulurlar. Bunun yerine bir veri dizisini prop olarak aktar ya da context kullan.

TypeScript'te children'ın tipi nedir?

React.ReactNode kullan. React'in render edebildiği her şeyi kapsar: öğeler, metinler, sayılar, diziler, null, undefined ve boolean'lar.

Coddy programlama dilleri çizimi

Coddy ile kodlamayı öğren

BAŞLA