Reactで1つのコンポーネントから複数のDOM要素を返す方法

記事内に広告が含まれています。

React で使う JSX では 1 つのコンポーネントから複数のDOM要素を通常の記述では返すことはできません。

但し React.Fragment を使えば 1 つのコンポーネントから複数のDOM要素を返えせるようになります。

この記事では React.Fragment の使い方を解説します。

React 環境の作成方法は以下のサイトを参照して作成してください。

Next.jsでReactを使った開発環境を作成する方法
Reactを利用してアプリケーションを作成する環境を作るには「npx create-react-app」もしくは「npx create-next-app 」コマンドを実行するだけで開発環境を簡単に準備することができます。

React のコンポーネントから複数要素を返す

通常 React で使う JSX では 1 つのコンポーネントから複数のDOM要素を通常の記述では返すことはできません。

import React  from "react" ;
import Button from "@material-ui/core/Button" ;

export default function Home(){
    return (
        <Button variant="contained" color="primary">
            OKボタン
        </Button>
        <Button variant="contained" color="secondary">
            CANCELボタン
        </Button>
    );
}

上記のコードを実行させると

Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>?
   7 |             OKボタン
   8 |         </Button>
>  9 |         <Button variant="contained" color="secondary">
     |         ^
  10 |             CANCELボタン
  11 |         </Button>
  12 |     );

とエラーになります。

これは Button コンポーネントが複数のトップノードとして return されているからです。

対処方法の 1 つとしては div タグで全体を囲めば一応の問題は解決します。

import React  from "react" ;
import Button from "@material-ui/core/Button" ;

export default function Home(){
    return (
        <div id="outer-div">
            <Button variant="contained" color="primary">
                OKボタン
            </Button>
            <Button variant="contained" color="secondary">
                CANCEボタン
            </Button>
        </div>
    );
}

でも、例えば table タグの td タグなどを編集して返すコンポーネントなどを作成する場合に divタグを挟むとおかしくなるので困ります。

import React  from "react" ;
import Button from "@material-ui/core/Button" ;

export default function MyTableCell(){
    return (
        <div id="outer-div">
            <tr><td>cell-01</td><td>cell-02</td></tr>
            <tr><td>cell-03</td><td>cell-04</td></tr>
        </div>
    );
}

これを実行すると

Expected server HTML to contain a matching <tr> in <div>.
    at tr
    at div
    at MyTableCell
    at MyApp

と警告が出てきます。

こんな時に使うのが React.Fragment です。

import React  from "react" ;
import Button from "@material-ui/core/Button" ;

export default function MyTableCell(){
    return (
        <React.Fragment>
            <tr><td>cell-01</td><td>cell-02</td></tr>
            <tr><td>cell-03</td><td>cell-03</td></tr>
        </React.Fragment>
    );
}

このように React.Fragment で囲めば JSX 返すDOM要素が複数個あっても、エラーや警告にならず、余計な div タグもでることはありません。
(上記の例では table タグがないよという別の警告にはなりますが。)

また React.Fragment は <>と</>(本当は半角文字で書く)で代用することも可能です。

import React  from "react" ;
import Button from "@material-ui/core/Button" ;

export default function MyTableCell(){
    return (
        <>
            <tr><td>cell-01</td><td>cell-02</td></tr>
            <tr><td>cell-03</td><td>cell-03</td></tr>
        </>
    );
}

まとめ

React の1 つのコンポネントから複数の DOM 要素を返したい時は React.Fragment タグを使えば警告の出ず、かつ余分な div タグなどを使うこと無い JSX を書くことができます。

タイトルとURLをコピーしました