落とし穴

Children οΏ½?δ½Ώη”¨γ―δΈ€θˆ¬ηš„γ§γ―γͺγγ€γ‚³γƒΌγƒ‰γŒε£Šγ‚Œγ‚„γ™γγͺγ‚‹ε―θƒ½ζ€§γŒγ‚γ‚ŠγΎγ™γ€‚δΈ€θˆ¬ηš„γͺ代替手�?�をご覧ください。

Children は、props である children γ‹γ‚‰ε—γ‘ε–γ£γŸ JSX γ‚’ζ“δ½œγ€ε€‰ζ›γ™γ‚‹γŸγ‚γ«η”¨γ„γΎγ™γ€‚

const mappedChildren = Children.map(children, child =>
<div className="Row">
{child}
</div>
);

γƒͺフゑレンス

Children.count(children)

Children.count(children) を呼び出して、children データ構造内�?子�?ζ•°γ‚’γ‚«γ‚¦γƒ³γƒˆγ—γΎγ™γ€‚

import { Children } from 'react';

function RowList({ children }) {
return (
<>
<h1>Total rows: {Children.count(children)}</h1>
...
</>
);
}

さらに例を見る

εΌ•ζ•°

  • children: γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγŒ props として受け取る children οΏ½?倀。

θΏ”γ‚Šε€€

当該 children ε†…ιƒ¨γ«γ‚γ‚‹γƒŽγƒΌγƒ‰οΏ½?数。

注意点

  • η©ΊοΏ½?γƒŽγƒΌγƒ‰οΌˆnull、undefinedγ€γŠγ‚ˆγ³γƒ–γƒΌγƒͺγ‚’γƒ³ε€€οΌ‰γ€ζ–‡ε­—εˆ—γ€ζ•°ε€€γ€γŠγ‚ˆγ³ React θ¦η΄ γŒγ€ε€‹γ€…οΏ½?γƒŽγƒΌγƒ‰γ¨γ—γ¦γ‚«γ‚¦γƒ³γƒˆγ•γ‚ŒγΎγ™γ€‚ι…εˆ—θ‡ͺ体は個εˆ₯οΏ½?γƒŽγƒΌγƒ‰γ¨γ—γ¦γ‚«γ‚¦γƒ³γƒˆγ•γ‚ŒγΎγ›γ‚“γŒγ€γοΏ½?ε­γ―γ‚«γ‚¦γƒ³γƒˆγ•γ‚ŒγΎγ™γ€‚React θ¦η΄ γ‚ˆγ‚Šζ·±γ„θ΅°ζŸ»γ―θ‘Œγ‚γ‚ŒγΎγ›γ‚“γ€‚θ¦η΄ γŒγοΏ½?ε ΄γ§γƒ¬γƒ³γƒ€γƒΌγ•γ‚Œγ‚‹γ‚γ‘γ§γ―γͺγ„γŸγ‚γ€ε­οΏ½?θ΅°ζŸ»γ‚‚θ΅·γγΎγ›γ‚“γ€‚γƒ•γƒ©γ‚°γƒ‘γƒ³γƒˆγ‚‚θ΅°ζŸ»γ•γ‚ŒγΎγ›γ‚“γ€‚

Children.forEach(children, fn, thisArg?)

Children.forEach(children, fn, thisArg?) を呼び出して、children データ構造内�?γγ‚Œγžγ‚ŒοΏ½?子に対して何らか�?コードを�?οΏ½θ‘Œγ™γ‚‹γ“γ¨γŒγ§γγΎγ™γ€‚

import { Children } from 'react';

function SeparatorList({ children }) {
const result = [];
Children.forEach(children, (child, index) => {
result.push(child);
result.push(<hr key={index} />);
});
// ...

さらに例を見る

εΌ•ζ•°

  • children: γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγŒ props として受け取る children οΏ½?倀。
  • fn: γγ‚Œγžγ‚ŒοΏ½?子に対して�?οΏ½θ‘Œγ—γŸγ„ι–’ζ•°γ€‚ι…εˆ—οΏ½? forEach パソッド οΏ½?コールバックに似ています。子を第 1 引数、そ�?むンデックスを第 2 εΌ•ζ•°γ¨γ—γ¦ε‘Όγ³ε‡Ίγ•γ‚ŒγΎγ™γ€‚γ‚€γƒ³γƒ‡γƒƒγ‚―γ‚Ήγ― 0 γ‹γ‚‰ε§‹γΎγ‚Šγ€ε‘Όγ³ε‡Ίγ—γ”γ¨γ«ε’—εŠ γ—γΎγ™γ€‚
  • 省η•₯可能 thisArg: fn ι–’ζ•°γŒε‘Όγ³ε‡Ίγ•γ‚Œγ‚‹ιš›οΏ½? this οΏ½?ε€€γ€‚ηœη•₯γ•γ‚ŒγŸε ΄εˆγ― undefined にγͺγ‚ŠγΎγ™γ€‚

θΏ”γ‚Šε€€

Children.forEach は undefined を返します。

注意点

  • η©ΊοΏ½?γƒŽγƒΌγƒ‰οΌˆnull、undefinedγ€γŠγ‚ˆγ³γƒ–γƒΌγƒͺγ‚’γƒ³ε€€οΌ‰γ€ζ–‡ε­—εˆ—γ€ζ•°ε€€γ€γŠγ‚ˆγ³ React θ¦η΄ γŒγ€ε€‹γ€…οΏ½?ε­γƒŽγƒΌγƒ‰γ¨γ—γ¦ζ‰±γ‚γ‚ŒγΎγ™γ€‚ι…εˆ—θ‡ͺ体は個εˆ₯οΏ½?γƒŽγƒΌγƒ‰γ¨γ—γ¦ζ‰±γ‚γ‚ŒγΎγ›γ‚“γŒγ€γοΏ½?δΈ­θΊ«γ―ε­γƒŽγƒΌγƒ‰γ¨γ—γ¦ζ‰±γ‚γ‚ŒγΎγ™γ€‚React θ¦η΄ γ‚ˆγ‚Šζ·±γ„θ΅°ζŸ»γ―θ‘Œγ‚γ‚ŒγΎγ›γ‚“γ€‚θ¦η΄ γŒγοΏ½?ε ΄γ§γƒ¬γƒ³γƒ€γƒΌγ•γ‚Œγ‚‹γ‚γ‘γ§γ―γͺγ„γŸγ‚γ€ε­οΏ½?θ΅°ζŸ»γ‚‚θ΅·γγΎγ›γ‚“γ€‚γƒ•γƒ©γ‚°γƒ‘γƒ³γƒˆγ‚‚θ΅°ζŸ»γ•γ‚ŒγΎγ›γ‚“γ€‚

Children.map(children, fn, thisArg?)

Children.map(children, fn, thisArg?) を呼び出して、children データ構造内�?γγ‚Œγžγ‚ŒοΏ½?ε­γ‚’γƒžγƒƒγƒ—οΌˆε€‰ζ›οΌ‰γ—γΎγ™γ€‚

import { Children } from 'react';

function RowList({ children }) {
return (
<div className="RowList">
{Children.map(children, child =>
<div className="Row">
{child}
</div>
)}
</div>
);
}

さらに例を見る

εΌ•ζ•°

  • children: γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγŒ props として受け取る children οΏ½?倀。
  • fnοΌšι…εˆ—οΏ½? map パソッド οΏ½?γ‚³γƒΌγƒ«γƒγƒƒγ‚―γ«δΌΌγŸγƒžγƒƒγƒ”γƒ³γ‚°ι–’ζ•°γ€‚ε­γ‚’η¬¬ 1 引数、そ�?むンデックスを第 2 εΌ•ζ•°γ¨γ—γ¦ε‘Όγ³ε‡Ίγ•γ‚ŒγΎγ™γ€‚γ‚€γƒ³γƒ‡γƒƒγ‚―γ‚Ήγ― 0 γ‹γ‚‰ε§‹γΎγ‚Šγ€ε‘Όγ³ε‡Ίγ—γ”γ¨γ«ε’—εŠ γ—γΎγ™γ€‚γ“οΏ½?閒数からは React γƒŽγƒΌγƒ‰γ‚’θΏ”γ™εΏ…θ¦γŒγ‚γ‚ŠγΎγ™γ€‚γ€γΎγ‚Šη©ΊοΏ½?γƒŽγƒΌγƒ‰οΌˆnull、undefinedγ€γΎγŸγ―γƒ–γƒΌγƒͺγ‚’γƒ³ε€€οΌ‰γ€ζ–‡ε­—εˆ—γ€ζ•°ε€€γ€React θ¦η΄ γ€γΎγŸγ―δ»–οΏ½? React γƒŽγƒΌγƒ‰οΏ½?ι…εˆ—γ§γ™γ€‚
  • 省η•₯可能 thisArg: fn ι–’ζ•°γŒε‘Όγ³ε‡Ίγ•γ‚Œγ‚‹ιš›οΏ½? this οΏ½?ε€€γ€‚ηœη•₯γ•γ‚ŒγŸε ΄εˆγ― undefined にγͺγ‚ŠγΎγ™γ€‚

θΏ”γ‚Šε€€

children が null または undefined οΏ½?ε ΄εˆγ€εŒγ˜ε€€γ‚’θΏ”γ—γΎγ™γ€‚

γγ‚Œδ»₯ε€–οΏ½?ε ΄εˆγ€fn ι–’ζ•°γ‹γ‚‰θΏ”γ•γ‚ŒγŸγƒŽγƒΌγƒ‰γ§ζ§‹ζˆγ•γ‚Œγ‚‹γƒ•γƒ©γƒƒγƒˆγͺι…εˆ—γ‚’θΏ”γ—γΎγ™γ€‚θΏ”γ•γ‚ŒγŸι…εˆ—γ«γ― null と undefined を陀くすべて�?γƒŽγƒΌγƒ‰γŒε«γΎγ‚ŒγΎγ™γ€‚

注意点

  • η©ΊοΏ½?γƒŽγƒΌγƒ‰οΌˆnull、undefinedγ€γŠγ‚ˆγ³γƒ–γƒΌγƒͺγ‚’γƒ³ε€€οΌ‰γ€ζ–‡ε­—εˆ—γ€ζ•°ε€€γ€γŠγ‚ˆγ³ React θ¦η΄ γŒγ€ε€‹γ€…οΏ½?ε­γƒŽγƒΌγƒ‰γ¨γ—γ¦ζ‰±γ‚γ‚ŒγΎγ™γ€‚ι…εˆ—θ‡ͺ体は個εˆ₯οΏ½?γƒŽγƒΌγƒ‰γ¨γ—γ¦ζ‰±γ‚γ‚ŒγΎγ›γ‚“γŒγ€γοΏ½?δΈ­θΊ«γ―ε­γƒŽγƒΌγƒ‰γ¨γ—γ¦ζ‰±γ‚γ‚ŒγΎγ™γ€‚React θ¦η΄ γ‚ˆγ‚Šζ·±γ„θ΅°ζŸ»γ―θ‘Œγ‚γ‚ŒγΎγ›γ‚“γ€‚θ¦η΄ γŒγοΏ½?ε ΄γ§γƒ¬γƒ³γƒ€γƒΌγ•γ‚Œγ‚‹γ‚γ‘γ§γ―γͺγ„γŸγ‚γ€ε­οΏ½?θ΅°ζŸ»γ‚‚θ΅·γγΎγ›γ‚“γ€‚γƒ•γƒ©γ‚°γƒ‘γƒ³γƒˆγ‚‚θ΅°ζŸ»γ•γ‚ŒγΎγ›γ‚“γ€‚

  • fn から key 付きで要素γͺいし要素�?ι…εˆ—γ‚’θΏ”γ™ε ΄εˆγ€θΏ”γ•γ‚ŒγŸθ¦η΄ οΏ½? key は、children οΏ½?ε―ΎεΏœγ™γ‚‹ε…ƒοΏ½?ι …οΏ½?οΏ½?キーとθ‡ͺε‹•ηš„γ«η΅εˆγ•γ‚ŒγΎγ™γ€‚fn から耇数�?θ¦η΄ γ‚’ι…εˆ—γ§θΏ”γ™ε ΄εˆγ€γγ‚Œγ‚‰οΏ½? key はそ�?ε†…ιƒ¨γ§γƒ­γƒΌγ‚«γƒ«γ«δΈ€ζ„γ§γ‚γ‚Œγ°εεˆ†γ§γ™γ€‚


Children.only(children)

Children.only(children)を呼び出すことで children γŒε˜δΈ€οΏ½? React 要素を葨していることを璺θͺγ—ます。

function Box({ children }) {
const element = Children.only(children);
// ...

εΌ•ζ•°

  • children: γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγŒ props として受け取る children οΏ½?倀。

θΏ”γ‚Šε€€

children γŒζœ‰εŠΉγͺθ¦η΄ γ§γ‚γ‚‹ε ΄εˆγ€γοΏ½?要素を返します。

γγ‚Œδ»₯ε€–οΏ½?ε ΄εˆγ€γ‚¨γƒ©γƒΌγ‚’γ‚Ήγƒ­γƒΌγ—γΎγ™γ€‚

注意点

  • こ�?パソッドは、children γ«ι…εˆ—οΌˆChildren.map οΏ½?θΏ”γ‚Šε€€γͺγ©οΌ‰γ‚’ζΈ‘γ™γ¨εΈΈγ«γ‚¨γƒ©γƒΌγ‚’γ‚Ήγƒ­γƒΌγ—γΎγ™γ€‚γ€γΎγ‚Šγ€children γŒε˜δΈ€θ¦η΄ οΏ½?ι…εˆ—γͺどではγͺγγ€ε˜δΈ€οΏ½? React 要素そ�?γ‚‚οΏ½?γ§γ‚γ‚‹γ“γ¨γ‚’εΌ·εˆΆγ—γΎγ™γ€‚

Children.toArray(children)

Children.toArray(children) を呼び出して、children γƒ‡γƒΌγ‚Ώζ§‹ι€ γ‹γ‚‰ι…εˆ—γ‚’δ½œζˆγ—γΎγ™γ€‚

import { Children } from 'react';

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

εΌ•ζ•°

  • children: γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγŒ props として受け取る children οΏ½?倀。

θΏ”γ‚Šε€€

children ε†…οΏ½?ε†…οΏ½?οΏ½οΏ½?γƒ•γƒ©γƒƒγƒˆγͺι…εˆ—γ‚’θΏ”γ—γΎγ™γ€‚

注意点

  • η©ΊγƒŽγƒΌγƒ‰οΌˆnull、undefinedγ€γŠγ‚ˆγ³γƒ–γƒΌγƒͺγ‚’γƒ³ε€€οΌ‰γ―θΏ”γ•γ‚Œγ‚‹ι…εˆ—γ‹γ‚‰γ―ηœγ‹γ‚ŒγΎγ™γ€‚θΏ”γ•γ‚Œγ‚‹θ¦η΄ οΏ½? key は、元�?要素�? key と、そ�?γƒγ‚Ήγƒˆγƒ¬γƒ™γƒ«γ‚„δ½οΏ½?γ‹γ‚‰θ¨ˆοΏ½?οΏ½γ•γ‚ŒγΎγ™γ€‚γ“γ‚Œγ«γ‚ˆγ‚Šγ€ι…εˆ—οΏ½?γƒ•γƒ©γƒƒγƒˆεŒ–γ«γ‚ˆγ‚ŠζŒ™ε‹•γŒε€‰εŒ–γ—γͺγ„γ“γ¨γŒδΏθ¨Όγ•γ‚ŒγΎγ™γ€‚

使用法

子�?倉換

γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγŒ children γƒ—γƒ­γƒ‘γƒ†γ‚£γ¨γ—γ¦ε—γ‘ε–γ£γŸε­οΏ½? JSX γ‚’ε€‰ζ›γ™γ‚‹γŸγ‚γ«γ€Children.map を呼び出します。

import { Children } from 'react';

function RowList({ children }) {
return (
<div className="RowList">
{Children.map(children, child =>
<div className="Row">
{child}
</div>
)}
</div>
);
}

上記�?例では、RowList γ―ε—γ‘ε–γ£γŸγ™γΉγ¦οΏ½?子を <div className="Row"> γ¨γ„γ†γ‚³γƒ³γƒ†γƒŠγ«γƒ©γƒƒγƒ—γ—γΎγ™γ€‚δΎ‹γˆγ°γ€θ¦ͺγ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγŒ 3 ぀�? <p> γ‚Ώγ‚°γ‚’ props η΅Œη”±γ§ children として RowList に渑すとしましょう。

<RowList>
<p>This is the first item.</p>
<p>This is the second item.</p>
<p>This is the third item.</p>
</RowList>

上記�? RowList οΏ½?οΏ½?οΏ½θ£…γ«γ‚ˆγ‚Šγ€ζœ€η΅‚ηš„γ«γƒ¬γƒ³γƒ€γƒΌγ•γ‚Œγ‚‹η΅ζžœγ―ζ¬‘οΏ½?γ‚ˆγ†γ«γͺγ‚ŠγΎγ™γ€‚

<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 は map() γ‚’δ½Ώγ£γ¦ι…εˆ—γ‚’ε€‰ζ›γ™γ‚‹ οΏ½?と似ています。違いは、children οΏ½?γƒ‡γƒΌγ‚Ώζ§‹ι€ γ‚’ιžε…¬ι–‹ (opaque) οΏ½?γ‚‚οΏ½?と見γͺγ™γΉγγ§γ‚γ‚‹γ“γ¨γ§γ™γ€‚γ“γ‚Œγ―γ€children が�?οΏ½ιš›γ«ι…εˆ—γ§γ‚γ‚‹ε ΄εˆγŒγ‚γ‚‹γ¨γ—γ¦γ‚‚γ€γγ‚Œγ‚’ι…εˆ—γ‚γ‚‹γ„γ―δ»–οΏ½?η‰ΉοΏ½?οΏ½οΏ½?γƒ‡γƒΌγ‚Ώεž‹γ§γ‚γ‚‹γ¨οΏ½?οΏ½?�してはγͺらγͺγ„γ¨γ„γ†ζ„ε‘³γ§γ™γ€‚γ“γ‚ŒγŒγ€ε­οΏ½?ε€‰ζ›γŒεΏ…θ¦γͺ場合には Children.map を使用すべき理由です。

import { Children } from 'react';

export default function RowList({ children }) {
  return (
    <div className="RowList">
      {Children.map(children, child =>
        <div className="Row">
          {child}
        </div>
      )}
    </div>
  );
}

さらに深くηŸ₯γ‚‹

γͺぜ children γŒεΈΈγ«ι…εˆ—γ¨γ―ι™γ‚‰γͺい�?γ‹οΌŸ

React では props として�? children γ―ιžε…¬ι–‹οΏ½?データ構造だと見γͺγ•γ‚ŒγΎγ™γ€‚γ€γΎγ‚ŠγοΏ½?ε…·δ½“ηš„γͺζ§‹ι€ γ«δΎε­˜γ—γ¦γ―γ„γ‘γͺγ„γ¨γ„γ†ζ„ε‘³γ§γ™γ€‚ε­γ‚’ε€‰ζ›γ—γŸγ‚Šγ€γƒ•γ‚£γƒ«γ‚Ώγƒͺγƒ³γ‚°γ—γŸγ‚Šγ€ζ•°γˆγŸγ‚Šγ™γ‚‹γŸγ‚γ«γ―γ€Children οΏ½?パソッドを使用すべきです。

οΏ½?οΏ½ιš›γ«γ―γ€children γƒ‡γƒΌγ‚Ώζ§‹ι€ γ―ε†…ιƒ¨ηš„γ«γ―γ—γ°γ—γ°ι…εˆ—γ¨γ—γ¦θ‘¨ηΎγ•γ‚ŒγΎγ™γ€‚γ—γ‹γ—γ€ε­γŒ 1 ぀だけ�?ε ΄εˆγ€React は不必要γͺパヒγƒͺγ‚ͺγƒΌγƒγƒΌγƒ˜γƒƒγƒ‰γ‚’ιΏγ‘γ‚‹γŸγ‚γ€δ½™εˆ†γͺι…εˆ—γ‚’δ½œζˆγ—γΎγ›γ‚“γ€‚children οΏ½?δΈ­θΊ«γ‚’η›΄ζŽ₯覗く�?ではγͺく、Children οΏ½?γƒ‘γ‚½γƒƒγƒ‰γ‚’δ½Ώη”¨γ™γ‚‹ι™γ‚Šγ€React γŒγƒ‡γƒΌγ‚Ώζ§‹ι€ οΏ½?οΏ½?�装方法を倉更してもあγͺた�?γ‚³γƒΌγƒ‰γ―ε£Šγ‚Œγšγ«ζΈˆγΏγΎγ™γ€‚

children γŒι…εˆ—γ§γ‚γ‚‹ε ΄εˆγ§γ‚‚γ€Children.map には便利γͺη‰Ήεˆ₯γͺζŒ―γ‚‹θˆžγ„γŒγ‚γ‚ŠγΎγ™γ€‚δΎ‹γˆγ°γ€Children.map γ―γ€θΏ”γ•γ‚ŒγŸθ¦η΄ οΏ½? key γ¨γ€ζΈ‘γ•γ‚ŒγŸ children にある key γ‚’η΅„γΏεˆγ‚γ›γΎγ™γ€‚γ“γ‚Œγ«γ‚ˆγ‚Šγ€δΈŠθ¨˜οΏ½?δΎ‹οΏ½?γ‚ˆγ†γ«γƒ©γƒƒγƒ—γ•γ‚Œγ¦γ‚‚ε…ƒοΏ½?子 JSX γŒγ‚­γƒΌγ‚’γ€Œε€±γ†γ€γ“γ¨γ―γ‚γ‚ŠγΎγ›γ‚“γ€‚

落とし穴

children データ構造は、JSX γ¨γ—γ¦ζΈ‘γ•γ‚Œγ‚‹γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆοΏ½?γƒ¬γƒ³γƒ€γƒΌγ•γ‚ŒγŸε‡ΊεŠ›γ‚’ε«γΏγΎγ›γ‚“γ€‚δ»₯δΈ‹οΏ½?例では、RowList γ«ζΈ‘γ•γ‚Œγ‚‹ children には 3 ぀ではγͺく 2 ぀�?をむテム�?γΏγŒε«γΎγ‚ŒγΎγ™γ€‚

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

こ�?γŸγ‚γ€γ“οΏ½?例では 2 ぀�?θ‘Œγƒ©γƒƒγƒ‘οΏ½?γΏγŒη”Ÿζˆγ•γ‚ŒγΎγ™οΌš

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

children γ‚’δ½Ώγ†ιš›γ«γ€<MoreRows /> οΏ½?γ‚ˆγ†γͺ内側�?γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆοΏ½?γƒ¬γƒ³γƒ€γƒΌε‡ΊεŠ›γ‚’ε–εΎ—γ™γ‚‹ζ–Ήζ³•γ―γ‚γ‚ŠγΎγ›γ‚“γ€‚γ“οΏ½?γŸγ‚ι€šεΈΈγ―δ»£ζ›Ώζ‰‹οΏ½?οΏ½οΏ½?γ„γšγ‚Œγ‹γ‚’δ½Ώη”¨γ™γ‚‹ζ–ΉγŒι©εˆ‡γ§γ™γ€‚


子�?γγ‚Œγžγ‚Œγ«ε―Ύγ—γ¦γ‚³γƒΌγƒ‰γ‚’οΏ½?οΏ½θ‘Œγ™γ‚‹

Children.forEach を呼び出すことで、children データ構造�?子�?γγ‚Œγžγ‚Œγ«ε―Ύγ—γ¦εεΎ©ε‡¦η†γ‚’θ‘ŒγˆγΎγ™γ€‚γ“γ‚Œγ―ε€€γ‚’θΏ”γ•γͺγ„γ€ι…εˆ—οΏ½? forEach γƒ‘γ‚½γƒƒγƒ‰γ«δΌΌγŸγ‚‚οΏ½?です。独θ‡ͺοΏ½?ι…εˆ—γ‚’ζ§‹η―‰γ™γ‚‹γͺど�?カスタムロジックを�?οΏ½θ‘Œγ™γ‚‹γŸγ‚γ«δ½Ώη”¨γ§γγΎγ™γ€‚

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

落とし穴

前述�?ι€šγ‚Šγ€children γ‚’δ½Ώη”¨γ™γ‚‹ιš›γ«γ€ε†…ε΄οΏ½?γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆοΏ½?γƒ¬γƒ³γƒ€γƒΌε‡ΊεŠ›γ‚’ε–εΎ—γ™γ‚‹ζ–Ήζ³•γ―γ‚γ‚ŠγΎγ›γ‚“γ€‚γ“οΏ½?γŸγ‚ι€šεΈΈγ―δ»£ζ›Ώζ‰‹οΏ½?οΏ½οΏ½?γ„γšγ‚Œγ‹γ‚’δ½Ώη”¨γ™γ‚‹ζ–ΉγŒι©εˆ‡γ§γ™γ€‚


子�?ζ•°γ‚’ζ•°γˆγ‚‹

Children.count(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>
  );
}

落とし穴

前述�?ι€šγ‚Šγ€children γ‚’δ½Ώη”¨γ™γ‚‹ιš›γ«γ€ε†…ε΄οΏ½?γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆοΏ½?γƒ¬γƒ³γƒ€γƒΌε‡ΊεŠ›γ‚’ε–εΎ—γ™γ‚‹ζ–Ήζ³•γ―γ‚γ‚ŠγΎγ›γ‚“γ€‚γ“οΏ½?γŸγ‚ι€šεΈΈγ―δ»£ζ›Ώζ‰‹οΏ½?οΏ½οΏ½?γ„γšγ‚Œγ‹γ‚’δ½Ώη”¨γ™γ‚‹ζ–ΉγŒι©εˆ‡γ§γ™γ€‚


ε­γ‚’ι…εˆ—γ«ε€‰ζ›γ™γ‚‹

Children.toArray(children) を呼び出して、children γƒ‡γƒΌγ‚Ώζ§‹ι€ γ‚’ι€šεΈΈοΏ½? JavaScript ι…εˆ—γ«ε€‰ζ›γ—γΎγ™γ€‚γ“γ‚Œγ«γ‚ˆγ‚Šγ€filter、sort、reverse γͺど�?η΅„γΏθΎΌγΏι…εˆ—γƒ‘γ‚½γƒƒγƒ‰γ‚’δ½Ώγ£γ¦ι…εˆ—γ‚’ζ“δ½œγ§γγΎγ™γ€‚

import { Children } from 'react';

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

落とし穴

前述�?ι€šγ‚Šγ€children γ‚’δ½Ώη”¨γ™γ‚‹ιš›γ«γ€ε†…ε΄οΏ½?γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆοΏ½?γƒ¬γƒ³γƒ€γƒΌε‡ΊεŠ›γ‚’ε–εΎ—γ™γ‚‹ζ–Ήζ³•γ―γ‚γ‚ŠγΎγ›γ‚“γ€‚γ“οΏ½?γŸγ‚ι€šεΈΈγ―δ»£ζ›Ώζ‰‹οΏ½?οΏ½οΏ½?γ„γšγ‚Œγ‹γ‚’δ½Ώη”¨γ™γ‚‹ζ–ΉγŒι©εˆ‡γ§γ™γ€‚


代替手�?οΏ½

補袳

こ�?セクションでθͺ¬ζ˜Žγ—ている�?は、δ»₯δΈ‹οΏ½?γ‚ˆγ†γ«γ—γ¦γ‚€γƒ³γƒγƒΌγƒˆγ™γ‚‹ Children APIοΌˆε€§ζ–‡ε­—οΏ½? CοΌ‰οΏ½?δ»£γ‚γ‚Šγ«δ½Ώγˆγ‚‹ζ‰‹οΏ½?�です。

import { Children } from 'react';

γ“γ‚Œγ‚’ children οΏ½?δ½Ώη”¨οΌˆε°ζ–‡ε­—οΏ½? cοΌ‰γ¨ζ··εŒγ—γͺγ„γ§γγ γ•γ„γ€‚γ“γ‘γ‚‰γ―θ‰―γ„γ“γ¨γ§γ‚γ‚Šγ€ζŽ¨ε₯¨γ•γ‚Œγ¦γ„γΎγ™γ€‚

耇数�?γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ‚’ε…¬ι–‹γ™γ‚‹

Children οΏ½?パソッドを使って children γ‚’ζ“δ½œγ™γ‚‹γ“γ¨γ§γ€γ—γ°γ—γ°γ‚³γƒΌγƒ‰γŒε£Šγ‚Œγ‚„γ™γγͺγ‚ŠγΎγ™γ€‚JSX γ§γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ« children γ‚’ζΈ‘γ™ε ΄εˆγ€ι€šεΈΈγ―γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ«γ‚ˆγ‚Šε€‹γ€…οΏ½?ε­γŒζ“δ½œγ•γ‚ŒγŸγ‚Šε€‰ζ›γ•γ‚ŒγŸγ‚Šγ™γ‚‹γ“γ¨γ‚’δΊˆζƒ³γ—γ¦γ„γͺいでしょう。

γ§γγ‚‹ι™γ‚Š Children パソッド�?δ½Ώη”¨γ―ιΏγ‘γ¦γγ γ•γ„γ€‚δΎ‹γˆγ°γ€RowList οΏ½?すべて�?子を <div className="Row"> γ§γƒ©γƒƒγƒ—γ—γŸγ„ε ΄εˆγ€Row γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ‚’γ‚¨γ‚―γ‚ΉγƒγƒΌγƒˆγ—γ€γ“οΏ½?γ‚ˆγ†γ«ε„θ‘Œγ‚’ζ‰‹ε‹•γ§γƒ©γƒƒγƒ—γ—γΎγ™γ€‚

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 γ‚’δ½Ώη”¨γ™γ‚‹ε ΄εˆγ¨γ―η•°γͺγ‚Šγ€γ“οΏ½?をプローチではすべて�?子をθ‡ͺε‹•ηš„γ«γƒ©γƒƒγƒ—γ—γ¦γγ‚ŒγΎγ›γ‚“γ€‚γ—γ‹γ—ε…ˆγ»γ©οΏ½? Children.map γ‚’δ½Ώη”¨γ—γŸδΎ‹γ¨ζ―”θΌƒγ—γ¦γ‚‚γ€γ“οΏ½?γ‚’γƒ—γƒ­γƒΌγƒγ«γ―γ€γ•γ‚‰γ«ε€šγοΏ½?γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ‚’ζŠ½ε‡Ίγ—γ¦γ‚‚ζ©Ÿθƒ½γ™γ‚‹γ¨γ„γ†εˆ©η‚ΉγŒγ‚γ‚ŠγΎγ™γ€‚δΎ‹γˆγ°γ€θ‡ͺ前�? MoreRows γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ‚’ζŠ½ε‡Ίγ—γ¦γ‚‚ζ©Ÿθƒ½γ—γΎγ™γ€‚

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

γ“γ‚Œγ― Children.map γ§γ―ζ©Ÿθƒ½γ—γΎγ›γ‚“γ€‚γͺぜγͺら、<MoreRows /> γŒε˜δΈ€οΏ½?ε­οΌˆγ€γΎγ‚Šε˜δΈ€οΏ½?θ‘ŒοΌ‰οΏ½?γ‚ˆγ†γ«γ€Œθ¦‹γˆγ‚‹γ€γ‹γ‚‰γ§γ™γ€‚


ι…εˆ—γ‚’ props として受けε…₯γ‚Œγ‚‹

ζ˜Žη€Ίηš„γ«ι…εˆ—γ‚’ props γ¨γ—γ¦ζΈ‘γ™γ“γ¨γ‚‚γ§γγΎγ™γ€‚δΎ‹γˆγ°γ€δ»₯δΈ‹οΏ½? RowList は rows γ¨γ„γ†ι…εˆ—γ‚’ props γ¨γ—γ¦ε—γ‘ε–γ‚ŠγΎγ™γ€‚

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 γ―ι€šεΈΈοΏ½? JavaScript οΏ½?ι…εˆ—γͺοΏ½?で、RowList γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ― map οΏ½?γ‚ˆγ†γͺ硄み込み�?ι…εˆ—γƒ‘γ‚½γƒƒγƒ‰γ‚’δ½Ώη”¨γ§γγΎγ™γ€‚

こ�?γƒ‘γ‚ΏγƒΌγƒ³γ―η‰Ήγ«γ€ε­γ¨δΈ€η·’γ«ζ§‹ι€ εŒ–γƒ‡γƒΌγ‚Ώγ¨γ—γ¦γ‚ˆγ‚Šε€šγοΏ½?ζƒ…ε ±γ‚’ζΈ‘γ—γŸγ„ε ΄εˆγ«ζœ‰η”¨γ§γ™γ€‚δ»₯δΈ‹οΏ½?例では、TabSwitcher γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ― props である tabs η΅Œη”±γ§γ‚ͺγƒ–γ‚Έγ‚§γ‚―γƒˆοΏ½?ι…εˆ—γ‚’ε—γ‘ε–γ‚ŠγΎγ™γ€‚

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 として子を渑す�?とは異γͺγ‚Šγ€γ“οΏ½?をプローチでは header οΏ½?γ‚ˆγ†γͺ追加�?γƒ‡γƒΌγ‚Ώγ‚’ε„γ‚’γ‚€γƒ†γƒ γ«ι–’ι€£δ»˜γ‘γ‚‹γ“γ¨γŒγ§γγΎγ™γ€‚tabs γ‚’η›΄ζŽ₯ζ“δ½œγ—γ¦γŠγ‚Šγ€γγ‚Œγ―ι…εˆ—γͺοΏ½?で、Children γƒ‘γ‚½γƒƒγƒ‰γ―εΏ…θ¦γ‚γ‚ŠγΎγ›γ‚“γ€‚


γƒ¬γƒ³γƒ€γƒΌγƒ—γƒ­γƒƒγƒ—γ‚’ε‘Όγ³ε‡Ίγ—γ¦γƒ¬γƒ³γƒ€γƒΌγ‚’γ‚«γ‚Ήγ‚Ώγƒžγ‚€γ‚Ίγ™γ‚‹

すべて�?をむテムに対して JSX γ‚’η”Ÿζˆγ—γ¦γŠγδ»£γ‚γ‚Šγ«γ€JSX を返す閒数を渑し、必要γͺときにそ�?閒数を呼び出してもらうこともできます。δ»₯δΈ‹οΏ½?例では、App γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ― renderContent という閒数を TabSwitcher γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ«ζΈ‘γ—γ¦γ„γΎγ™γ€‚TabSwitcher γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ―ιΈζŠžδΈ­οΏ½?γ‚Ώγƒ–οΏ½?みに対して renderContent を呼び出します。

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 οΏ½?γ‚ˆγ†γͺ props は、ユーアむンターフェース�?一部をど�?γ‚ˆγ†γ«γƒ¬γƒ³γƒ€γƒΌγ™γ‚‹γ‹γ‚’ζŒ‡οΏ½?�する props γ§γ‚γ‚‹γŸγ‚γ€γƒ¬γƒ³γƒ€γƒΌγƒ—γƒ­γƒƒγƒ— (render prop) γ¨ε‘Όγ°γ‚ŒγΎγ™γ€‚γ—γ‹γ—γ€γ“γ‚Œγ«γ€γ„γ¦η‰Ήεˆ₯γͺγ“γ¨γ―δ½•γ‚‚γ‚γ‚ŠγΎγ›γ‚“γ€‚γŸγΎγŸγŸγΎι–’ζ•°εž‹γ§γ‚γ‚‹γ¨γ„γ†γ γ‘οΏ½?ι€šεΈΈοΏ½? props γ«ιŽγŽγΎγ›γ‚“γ€‚

レンダープロップは閒数γͺοΏ½?γ§γ€ζƒ…ε ±γ‚’ζΈ‘γ™γ“γ¨γŒγ§γγΎγ™γ€‚δΎ‹γˆγ°γ€δ»₯δΈ‹οΏ½? RowList γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ―γ€ε„θ‘ŒοΏ½? id と index γ‚’ renderRow というレンダープロップに渑し、index γ‚’δ½Ώγ£γ¦εΆζ•°θ‘Œγ‚’γƒγ‚€γƒ©γ‚€γƒˆγ—γΎγ™γ€‚

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

こ�?γ‚ˆγ†γͺ方法でも、θ¦ͺγ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ¨ε­γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγŒγ€ε­οΏ½?ζ“δ½œγ‚’θ‘Œγ‚γšγ«ε”θͺΏε‹•δ½œγ§γγ‚‹γ¨γ„γ†γ“γ¨γ§γ™γ€‚


γƒˆγƒ©γƒ–γƒ«γ‚·γƒ₯ーティング

γ‚«γ‚Ήγ‚Ώγƒ γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆγ‚’ζΈ‘γ—γ¦γ„γ‚‹γŒγ€Children γƒ‘γ‚½γƒƒγƒ‰γŒγοΏ½?γƒ¬γƒ³γƒ€γƒΌη΅ζžœγ‚’θ‘¨η€Ίγ—γͺい

RowList にδ»₯δΈ‹οΏ½?γ‚ˆγ†γ« 2 ぀�?子を渑すとします。

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

RowList οΏ½?中で Children.count(children) γ‚’θ‘Œγ†γ¨γ€η΅ζžœγ― 2 にγͺγ‚ŠγΎγ™γ€‚MoreRows が 10 οΏ½?η•°γͺγ‚‹γ‚’γ‚€γƒ†γƒ γ‚’γƒ¬γƒ³γƒ€γƒΌγ™γ‚‹ε ΄εˆγ§γ‚‚γ€null γ‚’θΏ”γ™ε ΄εˆγ§γ‚‚γ€Children.count(children) γ―γ‚„γ―γ‚Š 2 にγͺγ‚ŠγΎγ™γ€‚RowList οΏ½?θ¦–η‚Ήγ‹γ‚‰γ―ε—γ‘ε–γ£γŸ JSX οΏ½?γΏγŒγ€Œθ¦‹γˆγ¦γ€γ„γ‚‹γ‹γ‚‰γ§γ™γ€‚MoreRows γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆοΏ½?δΈ­θΊ«γ―γ€Œθ¦‹γˆγ¦γ€γ„γΎγ›γ‚“γ€‚

こ�?εˆΆι™γ―γ‚³γƒ³γƒγƒΌγƒγƒ³γƒˆοΏ½?ζŠ½ε‡Ίγ‚’ε›°ι›£γ«γ—γΎγ™γ€‚γ“γ‚ŒγŒ Children を使用する�?ではγͺく、代替手�?�を使用すべき理由です。