HOWTO · React

React の子要素に props を渡す

React が props.children を通じてネストされたコンテンツをレンダリングする仕組みと、Context や React.cloneElement() で子コンテンツに追加の値を利用可能にする方法を学びます。

このページの内容

Reactコンポーネントは、タグの間にネストされたコンテンツを props.children で描画できます。そのコンテンツを描画しても、内部の要素にpropsが自動的に追加されるわけではありません。子孫コンポーネントと値を共有するにはContextを使い、特定の子要素にpropsを追加するには React.cloneElement() を使います。

たとえば、メッセージ用ダイアログには、テキストや絵文字、あるいは複数の要素を組み合わせた内容が渡されることがあります。再利用可能なダイアログコンポーネントは、あらかじめ内容を把握している必要はありません。ダイアログ本文を表示したい場所で props.children を描画できます。

Reactで子要素にpropsを渡す

ラッパーコンポーネントは、マークアップ内で {children} を返すことで、ネストされたコンテンツを表示できます。たとえば、function Box({ children }) { return <div>{children}</div>; } は、親が <Box> と </Box> の間に置いた内容を描画します。親コンポーネントでは、function App() { return <Box><Text /></Box>; } のように子要素を組み合わせられます。

この組み合わせでは、Text 要素が Box の children props として渡されますが、Text に color props が設定されるわけではありません。子要素に値が必要なら、<Text color="red" /> のように子要素を作るときに明示して渡すか、ラッパーから値を渡す必要がある場合は以下の方法を選びます。

これらのJSX断片はコンポーネントのつなぎ方を示すもので、アプリケーション内でReactが利用可能であることを前提としています。単独で実行できるファイルではなく、実行結果を報告するものでもありません。子要素は、たとえば function Text({ color }) { return <p style={{ color }}>Welcome to App</p>; } のような関数の引数で値を受け取れます。

ReactのContext APIで子要素にpropsを渡す

サブツリー内の複数のコンポーネントが同じ値を必要とし、中間の各コンポーネントを経由して値を渡すと不要な配線が増える場合は、Contextを使います。Contextを使うと、Provider配下のコンシューマーから値を利用できます。Contextはpropsとは別の仕組みであり、すべてのコンポーネントにpropsを一つずつ渡すものではありません。

たとえば、const ColorContext = React.createContext("black"); のようにContextを作成し、値が必要なコンテンツをProviderで囲みます。<ColorContext.Provider value="red">{children}</ColorContext.Provider> のように記述できます。子孫コンポーネントは const color = React.useContext(ColorContext); で値を読み取り、たとえば <p style={{ color }}>Welcome to App</p> のように適用できます。Providerの値は、そのProviderの内側で描画されるコンポーネントから利用できるため、必要なサブツリーをProviderで囲みます。デフォルト値が使われるのは、コンシューマーの上位に対応するProviderがない場合だけです。対応するProviderがある場合は、値が undefined であっても、コンシューマーにはデフォルト値ではなくProviderから渡された値が届きます。

この方法は、複数の子孫が使うテーマやロケールなどの値に適しています。追加の値を必要とする子要素が一つだけなら、要素を複製する方が直接的な場合があります。

React.cloneElement()でReactの子要素にpropsを渡す

React.cloneElement() は、有効なReact要素とpropsのセットから新しい要素を作成します。ラッパーは React.cloneElement(children, { color: "red" }) を使って、一つの子要素の color を追加または上書きし、ほかのpropsは保持できます。その子要素は、上記の Text の例のように color を利用できます。

この方法では、children が有効なReact要素一つであることを想定しています。props.children はテキスト、複数の要素、または別の形である場合もあります。そのため、React.cloneElement() を呼び出す前に形を確認するか、適切に処理してください。任意のテキストや複数の子要素を、一つの要素であるかのようにこの単一要素向けの形式に渡すことはできません。ラッパーでさまざまな内容を受け付けたい場合は、そのまま描画するか、子孫と値を共有する必要があればContextを使います。

サブツリー全体で使う値にはContextを選びます。ラッパーが特定の子要素一つを意図的に変更する場合は React.cloneElement() を選びます。どちらの方法でも、props.children の基本的な役割は変わりません。親から渡されたネストされたコンテンツを表します。