はじめに
props.childrenに対してpropsを持たせたい!となったので実装方法を探してみました。
*こちらは学習用メモです
*ドキュメントにあります。
cloneElement()
ReactにはcloneElementというAPIがあります。
今回はこちらを使用し、propsを渡していきました。
cloneElementの役割
element から新しい React 要素を複製して返します。結果の要素は元の要素の props と新しい props が浅くマージされたものを持ちます。新しい子要素は既存の子要素を置き換えます。key と ref は元の要素から保持されます。(引用: https://ja.reactjs.org/docs/react-api.html)
上記の通りにelementから新しいReact要素を複製という部分のelementがprops.childrenに値するという考えです。
使用する際はkey と ref は元の要素から保持されます。
こちらに注意しながら実装を行うといいかもしれません。
cloneElement/引数
React.cloneElement(
element, // <= 複製するelement
[props], // <= 複製するelementに適応させるprops
[...children] // <=複製するelementのchildrenとなる要素を指定
)
使用例
今回紹介する例はあくまで例なので、都合上props.childrenに渡したいという時に使用することと
本当にコンポーネント設計は正しいか確認の必要があると思います。
親コンポーネントの作成
import { Item } from './Item'
import { ItemChild } from './ItemChild'
export const ItemList = () => {
return (
<div>
<Item>
<ItemChild />
</Item>
</div>
)
}
props.childrenにpropsを渡す設定
export const Item = (props) => {
const items = [
{id: 1, name: 'hoge1'},
{id: 2, name: 'hoge2'}
]
// ここで渡す設定を行うコンポーネントを作成。
const ChildrenItem = (props) => {
// children === props.children, 渡したいprops === ...newProps
const { children, ...newProps } = props;
const childrenWithProps = React.Children.map(children, (child: React.ReactElement) => React.cloneElement(child, { ...newProps }));
}
return (
{
items.map((item, index) => {
// item、 indexがprops.childrenに渡したいprops
<ChildrenItem item={item} index={index}>
{props.children}
</ChildrenItem>
}
}
)
}
MyItemコンポーネント (propsを渡される props.children)
export const MyItem = (props) => {
// ItemListコンポーネントではpropsを設定していないがcloneElementの設定により受け取ることができる。
const { item, index } = props
return (
<div>
<div>index: { index }</div>
<div>itemName: { item.name }</div>
</div>
)
}
終わりに
実際に開発で使用した実装内容だと必要になったのですが、propsの順を追う時に若干厄介になる可能性があるので使用の際は本当に使う必要があるのかなど考える必要があることがわかりました。
参考
【React の最上位 API】 cloneElement()
https://qiita.com/NeGI1009/items/e6ad87320391c836bcf9
React.Chilrenについてあまり説明をしていなかったので知りたい方は下記
Reactのchildren探訪