Children (Alt Eleman)
Children, children prop’u olarak aldığınız JSX’i değiştirmenize ve dönüştürmenize olanak tanır
const mappedChildren = Children.map(children, child =>
<div className="Row">
{child}
</div>
);Başvuru Dokümanı
Children.count(children)
Children veri yapısındaki alt eleman sayısını saymak için Children.count(children) öğesini çağırın.
import { Children } from 'react';
function RowList({ children }) {
return (
<>
<h1>Toplam satır: {Children.count(children)}</h1>
...
</>
);
}Aşağıda daha fazla örneğe bakın.
Parametreler
children: Bileşeniniz tarafından alınanchildrenprop değeri.
Returns
Bu children içindeki node’ların sayısı.
Uyarılar
- Boş node’lar (
null,undefinedve Booleans), string’ler, sayılar ve React elemanları ayrı node’lar olarak sayılır. Diziler tek tek node’lar olarak sayılmaz, ancak alt elemanları sayılır. Çaprazlama React öğelerinden daha derine gitmez: bunlar işlenmez ve alt öğeleri çaprazlanmaz. Fragments geçilmez.
Children.forEach(children, fn, thisArg?)
Children veri yapısındaki her alt eleman için bazı kodlar çalıştırmak üzere Children.forEach(children, fn, thisArg?) öğesini çağırın.
import { Children } from 'react';
function SeparatorList({ children }) {
const result = [];
Children.forEach(children, (child, index) => {
result.push(child);
result.push(<hr key={index} />);
});
// ...Aşağıda daha fazla örneğe bakın
Parametreler
children: Bileşeniniz tarafından alınanchildrenprop değeri.fn: Her çocuk için çalıştırmak istediğiniz işlev, arrayforEachmethod callback’e benzer. İlk argüman olarak alt eleman ve ikinci argüman olarak indeksi ile çağrılacaktır. İndeks0dan başlar ve her çağrıda artar.- isteğe bağlı
thisArg:fnfonksiyonunun çağrılması gerekenthisdeğeri. Atlanırsa,tanımlanmamışolur.
Returns
Children.forEach öğesi undefined döndürür.
Uyarılar
- Boş node’lar (
null,undefinedve Booleans), string’ler, sayılar ve React elements ayrı node’lar olarak sayılır. Diziler tek tek node’lar olarak sayılmaz, ancak alt elemanları sayılır. Çaprazlama React öğelerinden daha derine gitmez: bunlar işlenmez ve alt öğeleri çaprazlanmaz. Fragments çaprazlanmaz.
Children.map(children, fn, thisArg?)
Alt eleman veri yapısındaki her alt elemani eşlemek veya dönüştürmek için Children.map(children, fn, thisArg?) öğesini çağırın.
import { Children } from 'react';
function RowList({ children }) {
return (
<div className="RowList">
{Children.map(children, child =>
<div className="Row">
{child}
</div>
)}
</div>
);
}Aşağıda daha fazla örneğe bakınız.
Parameters
children: Bileşeniniz tarafından alınanchildrenprop değeri.fn: arraymapmetodu callback’ine benzer eşleme fonksiyonu. İlk argüman olarak child’ı, ikinci argüman olarak indeksini alır. İndeks0’dan başlar ve her çağrıda artar. Bu fonksiyondan bir React node döndürmeniz gerekir. Bu; boş bir node (null,undefinedveya Boolean), bir string, bir number, bir React elementi ya da diğer React node’larından oluşan bir array olabilir.- optional
thisArg:fnfonksiyonunun çağrılacağıthisdeğeri. Eğer verilmezseundefinedolur.
Returns
Eğer children null veya undefined ise, aynı değeri döndürür.
Aksi takdirde, fn fonksiyonundan döndürdüğünüz node’lardan oluşan düz (flat) bir array döndürür. Dönen array, null ve undefined hariç tüm döndürdüğünüz node’ları içerir.
Uyarılar
-
Boş node’lar (
null,undefinedve Boolean’lar), string’ler, number’lar ve React elementleri ayrı birer node olarak sayılır. Array’ler tekil node olarak sayılmaz, ancak içlerindeki çocuklar sayılır. Traversal (gezme) React elementlerinin ötesine geçmez: render edilmezler ve içlerindeki çocuklar da traverse edilmez. Fragments da traverse edilmez. -
fnfonksiyonundan key’li bir element veya element array’i döndürürseniz, döndürülen elementlerin key’leri,childreniçindeki karşılık gelen orijinal item’ın key’i ile otomatik olarak birleştirilir.fniçinden birden fazla elementi array olarak döndürdüğünüzde, bu elementlerin key’lerinin yalnızca kendi aralarında lokal olarak benzersiz olması yeterlidir.
Children.only(children)
Alt elemanların tek bir React öğesini temsil ettiğini doğrulamak için Children.only(children) öğesini çağırın.
function Box({ children }) {
const element = Children.only(children);
// ...Parametreler
children: Bileşeniniz tarafından alınanchildrenprop değeri.
Returns
Eğer children geçerli bir eleman ise, bu elemanı döndürür.
Aksi takdirde hata verir.
Uyarılar
- Bu yöntem
childrenolarak bir dizi (örneğin,Children.map’in dönüş değeri) geçirirseniz her zaman hata fırlatır. Başka bir deyişle,children’ın tek bir React öğesi olmasını zorunlu kılar, ancak bu bir öğe içeren bir dizi olması anlamına gelmez.
Children.toArray(children)
Alt eleman veri yapısından bir dizi oluşturmak için Children.toArray(çocuklar) öğesini çağırın.
import { Children } from 'react';
export default function ReversedList({ children }) {
const result = Children.toArray(children);
result.reverse();
// ...Parametreler
children: Bileşeniniz tarafından alınanchildrenprop değeri.
Returns
children içindeki elemanların düz bir dizisini döndürür.
Uyarılar
- Boş node’lar (
null,undefinedve Booleans) döndürülen dizide atlanacaktır. Döndürülen öğelerin anahtarları, orijinal öğelerin anahtarlarından, iç içe geçme düzeylerinden ve konumlarından hesaplanacaktır. Bu, dizinin düzleştirilmesinin davranışta değişikliklere yol açmamasını sağlar.
Kullanım
Children’ı dönüştürmek
Bileşeninizin [children propu olarak aldığı](/learn/passing-props-to-a-component#passing-jsx-as-children) JSX çocuklarını dönüştürmek için Children.map` çağrısını yapın:
import { Children } from 'react';
function RowList({ children }) {
return (
<div className="RowList">
{Children.map(children, child =>
<div className="Row">
{child}
</div>
)}
</div>
);
}Yukarıdaki örnekte, RowList aldığı her children’ı bir <div className=“Row”> konteynerine sarar. Örneğin, ana bileşenin RowList öğesine children prop’u olarak üç <p> etiketi ilettiğini varsayalım:
<RowList>
<p>This is the first item.</p>
<p>This is the second item.</p>
<p>This is the third item.</p>
</RowList>Daha sonra, yukarıdaki RowList implementasyonu ile birlikte, son render edilmiş sonuç şu şekilde görünecektir:
<div className="RowList">
<div className="Row">
<p>This is the first item.</p>
</div>
<div className="Row">
<p>This is the second item.</p>
</div>
<div className="Row">
<p>This is the third item.</p>
</div>
</div>Children.map, array’leri map() ile dönüştürmeye benzer. Aradaki fark, children veri yapısının opaque (şeffaf olmayan) olarak kabul edilmesidir. Bu, bazen bir array olsa bile onun bir array ya da başka bir veri tipi olduğunu varsaymamanız gerektiği anlamına gelir. Bu yüzden, children üzerinde dönüşüm yapmanız gerekiyorsa Children.map kullanmalısınız.
import { Children } from 'react'; export default function RowList({ children }) { return ( <div className="RowList"> {Children.map(children, child => <div className="Row"> {child} </div> )} </div> ); }
Derinlemesine İnceleme
React’te children prop’u opaque (şeffaf olmayan) bir veri yapısı olarak kabul edilir. Bu, onun nasıl yapılandırıldığına güvenmemeniz gerektiği anlamına gelir. children üzerinde transform, filtreleme veya sayma işlemleri yapmak için Children metodlarını kullanmalısınız.
Pratikte children veri yapısı çoğu zaman içeride bir array olarak temsil edilir. Ancak yalnızca tek bir child varsa, React ekstra bir array oluşturmaz; çünkü bu gereksiz bellek kullanımına yol açar. Siz children’ın yapısına doğrudan erişmek yerine Children metodlarını kullandığınız sürece, React’in iç implementasyonu değişse bile kodunuz bozulmaz.
children bir array olsa bile Children.map bazı özel davranışlar sunar. Örneğin Children.map, dönen elementlerin key değerlerini, verilen children içindeki key’lerle birleştirir. Bu sayede, JSX children’lar wrapper’lara sarılsa bile orijinal key’lerini “kaybetmez”.
Her child için kod çalıştırma
Children.forEach fonksiyonunu, children veri yapısındaki her child üzerinde gezinmek için çağırabilirsiniz. Herhangi bir değer döndürmez ve array forEach metoduna benzer. Kendi array’inizi oluşturmak gibi özel mantıkları çalıştırmak için kullanılabilir.
import { Children } from 'react'; export default function SeparatorList({ children }) { const result = []; Children.forEach(children, (child, index) => { result.push(child); result.push(<hr key={index} />); }); result.pop(); // Remove the last separator return result; }
Counting children
Children.count(children) fonksiyonunu çağırarak children sayısını hesaplayabilirsiniz.
import { Children } from 'react'; export default function RowList({ children }) { return ( <div className="RowList"> <h1 className="RowListHeader"> Total rows: {Children.count(children)} </h1> {Children.map(children, child => <div className="Row"> {child} </div> )} </div> ); }
Children’ı array’e dönüştürme
Children.toArray(children) fonksiyonunu çağırarak children veri yapısını normal bir JavaScript array’ine dönüştürebilirsiniz. Bu sayede, filter, sort veya reverse gibi yerleşik array metodlarını kullanarak üzerinde işlem yapabilirsiniz.
import { Children } from 'react'; export default function ReversedList({ children }) { const result = Children.toArray(children); result.reverse(); return result; }
Alternatifler
Birden fazla bileşen sunma
Children metodlarıyla children üzerinde işlem yapmak genellikle kırılgan (fragile) kodlara yol açar. JSX içinde bir bileşene children verdiğinizde, genellikle o bileşenin bu children’ları tek tek manipüle etmesini veya dönüştürmesini beklemezsiniz.
Mümkün olduğunda Children metodlarını kullanmaktan kaçınmaya çalışın. Örneğin, RowList içindeki her child’ı <div className="Row"> ile sarmalamak istiyorsanız, bir Row bileşeni export edin ve her satırı manuel olarak onunla sarmalayın:
import { RowList, Row } from './RowList.js'; export default function App() { return ( <RowList> <Row> <p>This is the first item.</p> </Row> <Row> <p>This is the second item.</p> </Row> <Row> <p>This is the third item.</p> </Row> </RowList> ); }
Children.map kullanmaktan farklı olarak, bu yaklaşım her child’ı otomatik olarak sarmalamaz. Ancak, bu yaklaşımın Children.map ile yapılan önceki örneğe kıyasla önemli bir avantajı vardır: daha fazla bileşen çıkarsanız (extract etseniz) bile çalışmaya devam eder. Örneğin, kendi MoreRows bileşeninizi çıkarsanız bile hâlâ çalışır:
import { RowList, Row } from './RowList.js'; export default function App() { return ( <RowList> <Row> <p>This is the first item.</p> </Row> <MoreRows /> </RowList> ); } function MoreRows() { return ( <> <Row> <p>This is the second item.</p> </Row> <Row> <p>This is the third item.</p> </Row> </> ); }
Bu yaklaşım Children.map ile çalışmaz çünkü <MoreRows />’u tek bir child (ve tek bir row) olarak “görür”.
Prop olarak object array kabul etme
Ayrıca bir array’i açıkça prop olarak geçebilirsiniz. Örneğin, bu RowList bir rows array’ini prop olarak kabul eder:
import { RowList, Row } from './RowList.js'; export default function App() { return ( <RowList rows={[ { id: 'first', content: <p>This is the first item.</p> }, { id: 'second', content: <p>This is the second item.</p> }, { id: 'third', content: <p>This is the third item.</p> } ]} /> ); }
rows normal bir JavaScript array olduğu için, RowList bileşeni üzerinde map gibi yerleşik array metodlarını kullanabilir.
Bu pattern, children ile birlikte daha fazla bilgiyi yapılandırılmış veri olarak geçmek istediğiniz durumlarda özellikle kullanışlıdır. Aşağıdaki örnekte, TabSwitcher bileşeni tabs prop’u olarak object’lerden oluşan bir array alır:
import TabSwitcher from './TabSwitcher.js'; export default function App() { return ( <TabSwitcher tabs={[ { id: 'first', header: 'First', content: <p>This is the first item.</p> }, { id: 'second', header: 'Second', content: <p>This is the second item.</p> }, { id: 'third', header: 'Third', content: <p>This is the third item.</p> } ]} /> ); }
JSX olarak children geçirmekten farklı olarak, bu yaklaşım her bir öğeye header gibi ekstra verileri ilişkilendirmenize izin verir. tabs verisiyle doğrudan çalıştığınız ve bu bir array olduğu için Children metodlarına ihtiyaç duymazsınız.
Render prop çağırarak render’ı özelleştirme
Her bir öğe için JSX üretmek yerine, JSX döndüren bir fonksiyon da geçebilir ve bunu gerektiğinde çağırabilirsiniz. Bu örnekte, App bileşeni TabSwitcher bileşenine bir renderContent fonksiyonu geçirir. TabSwitcher ise bu fonksiyonu yalnızca seçili tab için çağırır:
import TabSwitcher from './TabSwitcher.js'; export default function App() { return ( <TabSwitcher tabIds={['first', 'second', 'third']} getHeader={tabId => { return tabId[0].toUpperCase() + tabId.slice(1); }} renderContent={tabId => { return <p>This is the {tabId} item.</p>; }} /> ); }
renderContent gibi bir prop’a render prop denir çünkü kullanıcı arayüzünün bir parçasının nasıl render edileceğini belirten bir prop’tur. Ancak bunda özel bir durum yoktur: sadece fonksiyon olan normal bir prop’tur.
Render prop’lar fonksiyon olduğu için onlara bilgi de geçebilirsiniz. Örneğin, bu RowList bileşeni her row’un id ve index değerini renderRow render prop’una geçirir ve renderRow bu index değerini kullanarak çift satırları highlight eder:
import { RowList, Row } from './RowList.js'; export default function App() { return ( <RowList rowIds={['first', 'second', 'third']} renderRow={(id, index) => { return ( <Row isHighlighted={index % 2 === 0}> <p>This is the {id} item.</p> </Row> ); }} /> ); }
Bu, parent ve child bileşenlerin children’ları manipulate etmeden birlikte nasıl çalışabileceğine dair başka bir örnektir.
Sorun giderme
Özel bir bileşen geçiriyorum ama Children metodları onun render sonucunu göstermiyor
Diyelim ki RowList bileşenine şu şekilde iki child geçiriyorsunuz:
<RowList>
<p>First item</p>
<MoreRows />
</RowList>Eğer RowList içinde Children.count(children) kullanırsanız 2 sonucunu alırsınız. MoreRows 10 farklı item render etse bile ya da null döndürse bile, Children.count(children) yine 2 olur. RowList açısından bakıldığında sadece kendisine gelen JSX’i “görür”. MoreRows bileşeninin iç detaylarını “göremez”.
Bu kısıtlama, bir bileşeni extract etmeyi zorlaştırır. Bu yüzden Children kullanmak yerine alternatifler tercih edilir.