はじめに
本記事はReact.Fragmentの使い方に関して記載します。
恥ずかしながら、筆者はReact開発をはじめて数ヶ月後に、React.Fragmentの存在を知りました。。涙
このテクニックをご存知でない方向けに記事を書きました。
問題点
Reactにて複数のエレメントをrender()関数にて返す必要がある場合、1つのタグにまとめる必要があります。
class Table extends React.Component {
render() {
return (
<table>
<tr>
<Columns column1="col1" column2="col2" />
</tr>
</table>
);
}
}
class Columns extends React.Component {
render() {
const { column1, column2 } = this.props;
// Error!!!
return (
<td>{column1}</td>
<td>{column2}</td>
);
}
}
ReactDOM.render(<Table />, document.getElementById("root"));
このとき、下記エラーが発生します。
index.js: Adjacent JSX elements must be wrapped in an enclosing tag
Columnsクラスにて2つのタグを返そうとしていますが、これはReactではNGです。
// NG case. 1つのタグにまとめる必要あり
return (
<td>{column1}</td>
<td>{column2}</td>
);
しばらくは私は
return (
<div>
<td>{column1}</td>
<td>{column2}</td>
</div>
);
divタグを追加するとエラーは解消しますが、無駄なタグがふくまれてしまいます。
<table>
<tr>
<div> <!-- このdivは不要 -->
<td>col1</td>
<td>col2</td>
</div>
</tr>
</table>
解決策
ReactにはReact.Fragmentタグが存在しており、このタグを追加することで、エラーは回避可能で、かつ無駄なタグが含まれることもなくなります。
class Columns extends React.Component {
render() {
const { column1, column2 } = this.props;
return (
<React.Fragment>
<td>{column1}</td>
<td>{column2}</td>
</React.Fragment>
);
}
}
生成されるHTMLは下記になります。無駄なタグは生成されません。
<table>
<tr>
<td>col1</td>
<td>col2</td>
</tr>
</table>
サンプルコードはこちら
https://codepen.io/japanese-engineer/pen/yxrQNv
補足
-
ツールによっては short syntax (<>>) の指定も可能です。ただ、多くのツールではshort syntax はサポートされてないので注意が必要です。
-
React.Fragmentはkeyを指定可能です。必要に応じてkeyを追加する必要があります。
下記例ではReact.Fragmentを配列として返しています。この場合、keyを追加しないと、Reactは警告を出します
function Glossary(props) {
return (
<dl>
{props.items.map(item => (
// Without the `key`, React will fire a key warning
<React.Fragment key={item.id}>
<dt>{item.term}</dt>
<dd>{item.description}</dd>
</React.Fragment>
))}
</dl>
);
}
まとめ
React にて複数の子エレメントを返す場合、React.Fragmentタグを使うことで、無駄なタグを省くことができます。