どうも、イソップです。
Reactアプリケーションでは、データをループ処理で一覧表示することが多いと思います。
その際によくあるのは、少しだけ違うコンポーネントが複数ある場合にループ用コンポーネントをたくさん作ってしまうこと。
例えば、参照するデータは同じだけど、表示するコンポーネントの見ためがほんの少しだけ違うとか。
そういうケースが増えると、非常に管理が煩雑になりがちです。
そこで、今回はループ用の親コンポーネントを用意して、
その中のデータ表示用コンポーネントを親コンポーネントから指定できる方法を紹介します。
コンポーネントを用意
次のようなデータがあります。
const data = [ 'foo', 'bar', 'baz' ];
この表示用コンポーネントを用意します。
データを表示するだけの子コンポーネント
class ListItem extends Component {
render() {
return(
<li>{this.props.text}</li>
);
}
}
アイコン付きの子コンポーネント
class IconListItem extends Component {
render() {
return(
<li>
<i className="icon"></i>
<span>{this.props.text}</span>
</li>
);
}
}
リスト表示するための親コンポーネント
import React, { Component } from 'react';
import ListItem from './ListItem';
class List extends Component {
render() {
const { data, component } = this.props;
let ChildComponent = component || ListItem;
return(
<ul>
{data.map((text, i) => {
return React.createElement(ChildComponent, { key: i, text });
})}
</ul>
);
}
}
React.createElement()
の部分が特に重要です。
React.createElement()
createElement
はReactのコンポーネントを作成するAPIで、React.Component
を介さず自分でReactコンポーネントを作成することができます。
React.createElement(
type,
[props],
[...children]
)
type
にはコンポーネント名か、クラスもしくは関数を渡すことができます。props
はプロパティをオブジェクトで渡します。children
はそのまま、コンポーネントのタグの中(<Hoge>...</Hoge>
)のコンテンツが渡ります。
React Top-Level API #createElement
親に子コンポーネントを渡してあげる
createElement
でコンポーネントを動的生成できるようにした List
コンポーネントは、次のように使います。
const data = [ 'foo', 'bar', 'baz' ];
...
<List data={data} component={IconListItem} />
component
プロパティに子コンポーネントを指定できるようにして、
List
コンポーネントの種類違いを作らないようにしています。
component
に何も指定しなければ、ListItem
が使われます。
Listコンポーネント
const { data, component } = this.props;
let ChildComponent = component || ListItem;
React.createElement
メソッドを活用することで、クリーンな設計にすることができます。