Tuzak

Children kullanımı nadirdir ve kırılgan koda yol açabilir. Yaygın alternatiflere bakın.

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ınan children prop değeri.

Returns

Bu children içindeki node’ların sayısı.

Uyarılar

  • Boş node’lar (null, undefined ve 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ınan children prop değeri.
  • fn: Her çocuk için çalıştırmak istediğiniz işlev, array forEach method callback’e benzer. İlk argüman olarak alt eleman ve ikinci argüman olarak indeksi ile çağrılacaktır. İndeks 0dan başlar ve her çağrıda artar.
  • isteğe bağlı thisArg: fn fonksiyonunun çağrılması gereken this değeri. Atlanırsa, tanımlanmamış olur.

Returns

Children.forEach öğesi undefined döndürür.

Uyarılar

  • Boş node’lar (null, undefined ve 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ınan children prop değeri.
  • fn: The mapping function, similar to the array map method callback. It will be called with the child as the first argument and its index as the second argument. The index starts at 0 and increments on each call. You need to return a React node from this function. This may be an empty node (null, undefined, or a Boolean), a string, a number, a React element, or an array of other React nodes.
  • optional thisArg: The this value with which the fn function should be called. If omitted, it’s undefined.

Returns

If children is null or undefined, returns the same value.

Otherwise, returns a flat array consisting of the nodes you’ve returned from the fn function. The returned array will contain all nodes you returned except for null and undefined.

Caveats

  • Empty nodes (null, undefined, and Booleans), strings, numbers, and React elements count as individual nodes. Arrays don’t count as individual nodes, but their children do. The traversal does not go deeper than React elements: they don’t get rendered, and their children aren’t traversed. Fragments don’t get traversed.

  • If you return an element or an array of elements with keys from fn, the returned elements’ keys will be automatically combined with the key of the corresponding original item from children. When you return multiple elements from fn in an array, their keys only need to be unique locally amongst each other.


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ınan children prop 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 children olarak 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ınan children prop değeri.

Returns

children içindeki elemanların düz bir dizisini döndürür.

Uyarılar

  • Boş node’lar (null, undefined ve 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>

Then, with the RowList implementation above, the final rendered result will look like this:

<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 is similar to to transforming arrays with map(). The difference is that the children data structure is considered opaque. This means that even if it’s sometimes an array, you should not assume it’s an array or any other particular data type. This is why you should use Children.map if you need to transform it.

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

Why is the children prop not always an array?

In React, the children prop is considered an opaque data structure. This means that you shouldn’t rely on how it is structured. To transform, filter, or count children, you should use the Children methods.

In practice, the children data structure is often represented as an array internally. However, if there is only a single child, then React won’t create an extra array since this would lead to unnecessary memory overhead. As long as you use the Children methods instead of directly introspecting the children prop, your code will not break even if React changes how the data structure is actually implemented.

Even when children is an array, Children.map has useful special behavior. For example, Children.map combines the keys on the returned elements with the keys on the children you’ve passed to it. This ensures the original JSX children don’t “lose” keys even if they get wrapped like in the example above.

Tuzak

The children data structure does not include rendered output of the components you pass as JSX. In the example below, the children received by the RowList only contains two items rather than three:

  1. <p>This is the first item.</p>
  2. <MoreRows />

This is why only two row wrappers are generated in this example:

import RowList from './RowList.js';

export default function App() {
  return (
    <RowList>
      <p>This is the first item.</p>
      <MoreRows />
    </RowList>
  );
}

function MoreRows() {
  return (
    <>
      <p>This is the second item.</p>
      <p>This is the third item.</p>
    </>
  );
}

There is no way to get the rendered output of an inner component like <MoreRows /> when manipulating children. This is why it’s usually better to use one of the alternative solutions.


Running some code for each child

Call Children.forEach to iterate over each child in the children data structure. It does not return any value and is similar to the array forEach method. You can use it to run custom logic like constructing your own array.

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;
}

Tuzak

As mentioned earlier, there is no way to get the rendered output of an inner component when manipulating children. This is why it’s usually better to use one of the alternative solutions.


Counting children

Call Children.count(children) to calculate the number of children.

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>
  );
}

Tuzak

As mentioned earlier, there is no way to get the rendered output of an inner component when manipulating children. This is why it’s usually better to use one of the alternative solutions.


Converting children to an array

Call Children.toArray(children) to turn the children data structure into a regular JavaScript array. This lets you manipulate the array with built-in array methods like filter, sort, or reverse.

import { Children } from 'react';

export default function ReversedList({ children }) {
  const result = Children.toArray(children);
  result.reverse();
  return result;
}

Tuzak

As mentioned earlier, there is no way to get the rendered output of an inner component when manipulating children. This is why it’s usually better to use one of the alternative solutions.


Alternatives

Not

This section describes alternatives to the Children API (with capital C) that’s imported like this:

import { Children } from 'react';

Don’t confuse it with using the children prop (lowercase c), which is good and encouraged.

Exposing multiple components

Manipulating children with the Children methods often leads to fragile code. When you pass children to a component in JSX, you don’t usually expect the component to manipulate or transform the individual children.

When you can, try to avoid using the Children methods. For example, if you want every child of RowList to be wrapped in <div className="Row">, export a Row component, and manually wrap every row into it like this:

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>
  );
}

Unlike using Children.map, this approach does not wrap every child automatically. However, this approach has a significant benefit compared to the earlier example with Children.map because it works even if you keep extracting more components. For example, it still works if you extract your own MoreRows component:

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>
    </>
  );
}

This wouldn’t work with Children.map because it would “see” <MoreRows /> as a single child (and a single row).


Accepting an array of objects as a prop

You can also explicitly pass an array as a prop. For example, this RowList accepts a rows array as a prop:

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> }
    ]} />
  );
}

Since rows is a regular JavaScript array, the RowList component can use built-in array methods like map on it.

This pattern is especially useful when you want to be able to pass more information as structured data together with children. In the below example, the TabSwitcher component receives an array of objects as the tabs prop:

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>
      }
    ]} />
  );
}

Unlike passing the children as JSX, this approach lets you associate some extra data like header with each item. Because you are working with the tabs directly, and it is an array, you do not need the Children methods.


Calling a render prop to customize rendering

Instead of producing JSX for every single item, you can also pass a function that returns JSX, and call that function when necessary. In this example, the App component passes a renderContent function to the TabSwitcher component. The TabSwitcher component calls renderContent only for the selected tab:

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>;
      }}
    />
  );
}

A prop like renderContent is called a render prop because it is a prop that specifies how to render a piece of the user interface. However, there is nothing special about it: it is a regular prop which happens to be a function.

Render props are functions, so you can pass information to them. For example, this RowList component passes the id and the index of each row to the renderRow render prop, which uses index to highlight even rows:

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> 
        );
      }}
    />
  );
}

This is another example of how parent and child components can cooperate without manipulating the children.


Troubleshooting

I pass a custom component, but the Children methods don’t show its render result

Suppose you pass two children to RowList like this:

<RowList>
<p>First item</p>
<MoreRows />
</RowList>

If you do Children.count(children) inside RowList, you will get 2. Even if MoreRows renders 10 different items, or if it returns null, Children.count(children) will still be 2. From the RowList’s perspective, it only “sees” the JSX it has received. It does not “see” the internals of the MoreRows component.

The limitation makes it hard to extract a component. This is why alternatives are preferred to using Children.