JSXはJavaScript XMLの略で、開発者JavaScriptファイルにHTMLなどのコードを書けるようにするReactで便利な構文拡張です。

特にJSXを使い始めたばかりの頃は、「JSX expressions must have one parent element」(JSX式には親要素が1つ必要です)というエラーメッセージに遭遇することがあります。このエラーは、複数の要素が親要素でラップされずに1つの式で返された場合に発生します。

また、類似のエラーメッセージに、「Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>…</>?」(隣接するJSX要素は、タグで囲む必要があります)もあります。

今回はReact開発者向けに、このエラーの解決方法をいくつかご紹介していきます。

「JSX expressions must have one parent element」エラーの原因

JSXには、常に単一の要素を返すというルールがあります。このルールはReactにも適用され、どのコンポーネントも単一のルート要素しか返せません。

これは、コンポーネントのレンダリングの際に、最終的にページにレンダリングするHTMLに対応した仮想DOMツリーが作成されるためです。JSXに複数のルート要素があると、Reactがそれらを処理することができず、「JSX expressions must have one parent element」や「Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>…</>?」のようなエラーメッセージを返します。

例えば、以下のJSXコードのレンダリングを試行してみます。

function App() {
    return (
        <h1>Hello, world!</h1>
        <p>これは段落です。</p>
    )
}

すると以下のような「JSX expressions must have one parent element」エラーメッセージが表示されます。

「JSX expressions must have one parent element」エラーメッセージ
「JSX expressions must have one parent element」エラーメッセージ

または以下のような「Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>…</>?」エラーメッセージになることもあります。

「Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>…</>?」エラーメッセージ
「Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>…</>?」エラーメッセージ

これらのエラーは、2つのルート要素(<h1><p>)が返されているために発生します。

JSXは複数の値を返すことができないため、関数と同じように動作します(配列で囲まれている場合を除く─配列は1つの値とみなされる)。

function myFunc() {
  return value1;
  return value2;
}

上記の関数では1つ目のreturn文が常に実行されるため、2つ目のreturn文まで到達しません。

「JSX expressions must have one parent element」エラーを解決する(3つの方法)

このエラーを解決する方法は、大きく分けて3つあります。

  • Divタグでラップする
  • Fragment(<>と</>)でラップする
  • React.Fragmentコンポーネントを使用する

1. すべての要素をDivタグでラップする

このエラーを解決する最も簡単な方法は、複数のJSX要素を<div>などの1つの親要素でラップすることです。

要素を1つのまとまりとしてグループ化することで、レンダリングすることができます。以下、例を見てみましょう。

function App() {
    return (
        <div>
            <h1>Hello, world!</h1>
           <p>これは段落です。</p>
        </div>
    )
}

上の例では、<h1><p>要素が、親要素となる<div>要素でラップされています。

2. すべての要素をFragmentでラップする

エラーメッセージ「JSX expressions must have one parent element」または「Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>…</>?」を解決するもう1つの方法では、JSX Fragmentを使用します。

Fragment(フラグメント)はReactの組み込み機能で、DOMに余分なノードを追加することなく、子要素のリストをグループ化します。これにより、レンダリングされるHTMLに余計なDOMノードを加えず、複数の要素を単一の親要素でラップすることができます。例を見てみます。

function App() {
    return (
        <>
            <h1>Hello, world!</h1>
            <p>これは段落です。</p>
        </>
    )
}

JSX Fragment(<>と</>)を使用して複数の要素をラップしており、このFragmentは親要素として機能します。

3. すべての要素をReact.Fragmentでラップする

最後に、通常の要素の代わりにReact.Fragment要素を使用することもできます。

これは、Fragmentと同じように機能しますが、もう少し明示的で、親要素に特定のキーやその他のプロパティを与えたい場合に便利です。例は以下のとおりです。

function App() {
    return (
        <React.Fragment>
            <h1>Hello, world!</h1>
            <p>これは段落です。</p>
       </React.Fragment>
    )
}

上の例では、親要素として通常の要素の代わりに、React.Fragmentを使用しています。複数の要素を <></>で囲むことで、レンダリングされるHTMLに余計なノードを追加することなく、要素をグループ化できます。

React.Fragmentコンポーネントを使用するには、Reactをインポートする必要があります。また、Fragment自体にpropsやclassNamestyleidを追加することができるため、Fragment内の要素のグループにスタイルなどの属性を適用したい場合に有用です。

条件文の「JSX expressions must have one parent element」エラーを解決する

Reactで条件付き三項演算子を扱う場合にも、「JSX expressions must have one parent element」や「Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>…</>?」のようなエラーメッセージが表示されることがあります。

これは、条件文の中から複数の要素が返された場合に発生します。この場合、Reactが正しくレンダリングを行うことができず、いずれかのエラーを返します。

function App() {
    return (
        <div>
            {condition ? (
                <h1>見出し1</h1>
                <p>段落1</p>
                        ) : (
                <h2>見出し2</h2>
                <p>段落2</p>
            )}
        </div>
    )
}

このエラーも、今回ご紹介した3つの方法のいずれかで解決可能です。Fragment(<></>)または<div>要素を使用するのがお勧めです。

function App() {
    return (
        <div>
            {condition ? (
                <>
                    <h1>見出し1</h1>
                   <p>段落1</p>
                </>
            ) : (
                <>
                    <h2>見出し2</h2>
                    <p>段落2</p>
                </>
            )
            }
        </div>
    )
}

まとめ

エラーメッセージ「JSX expressions must have one parent element」または「Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>…</>?」は、React初心者が遭遇しがちな問題です。

<div>要素を使用するのが最も簡単な解決策ですが、DOMに不要なdivタグを追加することになります。Fragmentを使用すれば、DOMに余計なノードを追加することなく、すっきりエラーを解決することができます。

この問題に遭遇した経験はありますか?また、今回ご紹介したもの以外にも解決策をご存知でしたら、以下のコメント欄でぜひお聞かせください。