解析エラー:隣接するJSX要素は囲みタグで囲む必要があります


467

私が設定しReact.jsた変数がの場合にのみレンダリングされるようにアプリを設定しようとしていますtrue

私のレンダー関数の設定方法は次のようになります。

render: function() {
    var text = this.state.submitted ? 'Thank you!  Expect a follow up at '+email+' soon!' : 'Enter your email to request early access:';
    var style = this.state.submitted ? {"backgroundColor": "rgba(26, 188, 156, 0.4)"} : {};
    return (
    <div>

if(this.state.submitted==false) 
{

      <input type="email" className="input_field" onChange={this._updateInputValue} ref="email" value={this.state.email} />

      <ReactCSSTransitionGroup transitionName="example" transitionAppear={true}>
      <div className="button-row">
         <a href="#" className="button" onClick={this.saveAndContinue}>Request Invite</a>
     </div>
     </ReactCSSTransitionGroup>
}
   </div>
    )
  },

基本的に、ここで重要な部分はそのif(this.state.submitted==false)部分です(div送信された変数がに設定されているときにこれらの要素が表示されるようにしたいfalse)。

しかし、これを実行すると、質問でエラーが発生します。

キャッチされなかったエラー:解析エラー:行38:隣接するJSX要素は囲みタグでラップする必要があります

ここの問題は何ですか?そして、これを機能させるために何を使用できますか?


3
stackoverflow.com/questions/25034994/… ここにいる他の人々は親要素を使用するように言っているだけですが、それは不必要かもしれません。この古いバージョンの質問には、配列を使用した興味深い答えがあります。
Meow

回答:


637

コンポーネントを囲むタグの間に配置する必要があります。つまり、

// WRONG!

return (  
    <Comp1 />
    <Comp2 />
)

代わりに:

// Correct

return (
    <div>
       <Comp1 />
       <Comp2 />
    </div>
)

編集:Fragments APIに関するJoe Clay氏のコメント

// More Correct

return (
    <React.Fragment>
       <Comp1 />
       <Comp2 />
    </React.Fragment>
)

// Short syntax

return (
    <>
       <Comp1 />
       <Comp2 />
    </>
)

4
テーブルで2行を一緒に印刷するとどうなりますか?<tr>をどのようにラップできますか?
ホセ

235

この質問に答えるのは遅いですが、説明に追加すると思いました。

これは、コード内の任意の場所で2つの要素を同時に返すために発生します。

例えば

return(
    <div id="div1"></div>
    <div id="div1"></div>
  )

要素でラップする必要があります。例えば

 return(
      <div id="parent">
        <div id="div1"></div>
        <div id="div1"></div>
      </div>
      )


より詳細な説明

以下のjsxコードが変換されます

class App extends React.Component {
  render(){
    return (
      <div>
        <h1>Welcome to React</h1>
      </div>
    );
  }
}

これに

_createClass(App, [{
    key: 'render',
    value: function render() {
      return React.createElement(
        'div',
        null,
        React.createElement(
          'h1',
          null,
          'Welcome to React'
        )
      );
    }
  }]);

でもこれをやれば

class App extends React.Component {
  render(){
    return (
        <h1>Welcome to React</h1>
        <div>Hi</div>
    );
  }
}

これはこれに変換されます(単に説明のために、実際にはerror : Adjacent JSX elements must be wrapped in an enclosing tag

_createClass(App, [{
    key: 'render',
    value: function render() {
      return React.createElement(
        'div',
        null,
       'Hi'
      ); 
    return React.createElement(
          'h1',
          null,
          'Welcome to React'
        )
    }
  }]);

上記のコードでは、メソッド呼び出しから2回返そうとしていることがわかりますが、これは明らかに間違っています。

編集-React 16および自身のワードにおける最新の変更:

ラップするdivを追加したくない場合や、複数の子コンポーネントを返したい場合は、を使用できますReact.Fragments

React.Fragments 少し高速でメモリ使用量が少ない(余分なDOMノードを作成する必要がなく、雑然としたDOMツリーが少ない)。

(React 16.2.0では)

render() {
  return (
    <>
       React fragments.
      <h2>A heading</h2>
      More React fragments.
      <h2>Another heading</h2>
      Even more React fragments.
    </>
  );
}

または

render() {
  return (
    <React.Fragments>
       React fragments.
      <h2>A heading</h2>
      More React fragments.
      <h2>Another heading</h2>
      Even more React fragments.
    <React.Fragments/>
  );
}

または

render() {
 return [
  "Some text.",
  <h2 key="heading-1">A heading</h2>,
  "More text.",
  <h2 key="heading-2">Another heading</h2>,
  "Even more text."
 ];
}

115

React要素は1つの要素のみを返す必要があります。両方のタグを別の要素タグでラップする必要があります。

また、レンダリング関数が何も返さないこともわかります。コンポーネントは次のようになります。

var app = React.createClass({
    render () {
        /*React element can only return one element*/
        return (
             <div></div>
        )
    }
})

またif、返された要素内ではステートメントを使用できないことに注意してください。

render: function() {
var text = this.state.submitted ? 'Thank you!  Expect a follow up at '+email+' soon!' : 'Enter your email to request early access:';
var style = this.state.submitted ? {"backgroundColor": "rgba(26, 188, 156, 0.4)"} : {};
    if(this.state.submitted==false) {
        return <YourJSX />
    } else {
        return <YourOtherJSX />
    }
},

これは「if」の問題には対応していません。render関数内の「if」を削除すると、正常に機能します。
user1072337 2015

1
再調整された要素内のif文は使用できないことに注意してください。私の更新された答えを見てください
Matan Gubkin

99

他の回答が示唆しているように別のdivでラップしたくない場合は、配列でラップすることもできます。

// Wrong!
return (  
   <Comp1 />
   <Comp2 />
)

それは次のように書くことができます:

// Correct!
return (  
    [<Comp1 />,
    <Comp2 />]
)

上記は警告を生成することに注意してください: Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of 'YourComponent'.

これを修正するkeyには、コンポーネントに属性を追加します。手動で追加する場合は、次のように追加します。

return (  
    [<Comp1 key="0" />,
    <Comp2 key="1" />]
)

キーに関するいくつかの詳細はここにあります:構成vs継承


7
私はこれを試しました、そしてそれは私にエラーを与えます。有効なReact要素(またはnull)を返す必要があります。未定義、配列、またはその他の無効なオブジェクトを返した可能性があります。
prasadmsvs

3
@prasadmsvs +1 invariant.js:39 Uncaught Invariant Violation:CommitFilter.render():有効なReactComponentを返す必要があります。未定義、配列、またはその他の無効なオブジェクトを返した可能性があります。
Svetlana Ivanova

1
これは、ラッパー要素を回避する必要がある/したい場合に最適なソリューションです。
bloudermilk 2016年

2
@aaaaaa現在のReact調整サーバーの動作方法が原因で、それは不可能です。これはスタックであり、調整は再帰的に行われます。React 16ではこれが修正され、配列を返すことができるようになりました。
natnai 2017年

1
github.com/iamdustan/tiny-react-rendererは、すべての反応開発者が読むべき優れたリポジトリです。一度実行すると、現在のreactの実装では複数の子を返すことができない理由がすぐに明らかになるはずです。
natnai 2017年

49

問題

解析エラー:隣接するJSX要素は囲みタグで囲む必要があります

これは、複数の兄弟JSX要素を誤った方法で返そうとしていることを意味します。HTMLではなくJSXを作成していることを忘れないでください。コードがJSXからJavaScriptに変換されます。例えば:

render() {
  return (<p>foo bar</p>);
}

に変換されます:

render() {
  return React.createElement("p", null, "foo bar");
}

一般にプログラミングに慣れていない限り、(任意の言語の)関数/メソッドは任意の数のパラメーターを受け取りますが、常に1つの値しか返さないことはすでに知っています。そのため、createElement()動作に基づいて複数の兄弟コンポーネントを返そうとすると問題が発生することがわかります。1つの要素のパラメーターのみを受け取り、それを返します。したがって、1回の関数呼び出しで複数の要素を返すことはできません。


これがなぜ機能するのか疑問に思ったことがあるなら...

render() {
  return (
    <div>
      <p>foo</p>
      <p>bar</p>
      <p>baz</p>
    </div>
  );
}

しかし、これは...

render() {
  return (
    <p>foo</p>
    <p>bar</p>
    <p>baz</p>
  );
}

これは、最初のスニペットでは、両方の<p>-elementsが-elementの一部でchildrenあるため<div>です。それらがその一部であるchildren場合、無制限の数の兄弟要素を表現できます。これがどのようにトランスパイルするか見てみましょう:

render() {
  return React.createElement(
    "div",
    null,
    React.createElement("p", null, "foo"),
    React.createElement("p", null, "bar"),
    React.createElement("p", null, "baz"),
  );
}

ソリューション

実行しているReactのバージョンに応じて、これに対処するいくつかのオプションがあります。

  • フラグメントを使用する(React v16.2以降のみ!)

    React v16.2以降、Reactはフラグメントをサポートしています、子を直接返すノードレスコンポーネントであるをています。

    配列で子を返す(下記を参照)には、いくつかの欠点があります。

    • 配列内の子はコンマで区切る必要があります。
    • 配列内の子には、Reactのキー警告を防ぐためのキーが必要です。
    • 文字列は引用符で囲む必要があります。

    これらはフラグメントの使用から除外されます。以下は、フラグメントにラップされた子の例です。

    render() {
      return (
        <>
          <ChildA />
          <ChildB />
          <ChildC />
        </>
      );
    }

    脱糖するもの:

    render() {
      return (
        <React.Fragment>
          <ChildA />
          <ChildB />
          <ChildC />
        </React.Fragment>
      );
    }

    最初のスニペットにはBabel v7.0以降が必要です。


  • 配列を返す(React v16.0以降のみ!)

    React v16以降、React Componentsは配列を返すことができます。これは、すべての兄弟コンポーネントを親コンポーネントでラップせざるを得なかった以前のバージョンのReactとは異なります。

    つまり、次のことができるようになります。

    render() {
      return [<p key={0}>foo</p>, <p key={1}>bar</p>];
    }

    これは以下に移ります:

    return [React.createElement("p", {key: 0}, "foo"), React.createElement("p", {key: 1}, "bar")];

    上記は配列を返すことに注意してください。Reactバージョン16以降では、配列は有効なReact要素です。以前のバージョンのReactでは、配列は有効な戻りオブジェクトではありません!

    また、以下は無効です(配列を返す必要があります)。

    render() {
      return (<p>foo</p> <p>bar</p>);
    }

  • 要素を親要素で囲む

    他のソリューションでは、兄弟コンポーネントをでラップする親コンポーネントを作成しますchildren。これは、この問題に対処する最も一般的な方法であり、Reactのすべてのバージョンで機能します。

    render() {
      return (
        <div>
          <h1>foo</h1>
          <h2>bar</h2>
        </div>
      );
    }

    注:詳細とこの変換の仕方については、この回答の上部をもう一度ご覧ください


@Grievoushead、コンポーネントではなく、いいえ。子供のみ。
Chris

1
いいですね、問題を修正しました。
ソハン

1
他の解決策を説明する時間を割いてくれたChrisに感謝します!
Marvel Moe

on React v16.4の最初の例は、次を使用しても機能しません:<><React.Fragment>:(
vsync

@vsyncその構文のサポートは、ビルド環境によって異なります。babelがまだそれをサポートしているかどうか、サポートしている場合はどのバージョンかわからない。
Chris

22

React 16.0.0では、レンダーから複数のコンポーネントを配列として返すことができます。

return ([
    <Comp1 />,
    <Comp2 />
]);

React 16.4.0では、Renderから複数のコンポーネントをFragmentタグで返すことができます。断片

return (
<React.Fragment>
    <Comp1 />
    <Comp2 />
</React.Fragment>);

Future Reactでは、この省略形の構文を使用できます。(多くのツールはまだそれをサポートしていないので<Fragment>、ツールが追いつくまで明示的に記述したいかもしれません。)

return (
<>
    <Comp1 />
    <Comp2 />
</>)

1
,コンポーネント間のa を忘れました。それは配列なので、その中の各要素を分離する必要があります。
Chris

ありません<Fragment>、それは<React.Fragment>です。あなた自身のリンクでそう言う
VSYNC

2
破壊する場合はimport React { Fragment } from 'react';、次のように使用します<Fragment >
Morris S

7

コンポーネントをラップしない場合は、以下のメソッドのように記述できます。

の代わりに:

return(
  <Comp1 />
  <Comp2 />
     );

あなたはこれを書くことができます:

return[(
 <Comp1 />
),
(
<Comp2 />
) ];

6

親要素のdivを使用してすべての要素をラップすることも、高次コンポーネント(HOC)の概念を使用することも非常に簡単です。つまり、反応jsアプリケーションに非常に役立ちます。

render() {
  return (
    <div>
      <div>foo</div>
      <div>bar</div>
    </div>
  );
}

または別の最良の方法は、HOCです。プロジェクトにhoc.jsファイルを追加し、これらのコードを追加するだけで、非常に単純ではありません。

const aux = (props) => props.children;
export default aux;

使用する場所にhoc.jsファイルをインポートします。div要素でラップする代わりに、hocでラップできます。

import React, { Component } from 'react';
import Hoc from '../../../hoc';

    render() {
      return (
    <Hoc>
        <div>foo</div>
        <div>bar</div>
    </Hoc>
      );
    }

このコードは質問に答えることがありますが、問題を解決する方法や理由に関する追加のコンテキストを提供すると、回答の長期的な価値が向上します。これを読んでください
Shanteshwar Inde、

あなたが話している機能、つまり、reactjsでHOCと呼ばれる機能。props.childrenを意味します
Fazal

4

JSX式には最も外側の要素を1つだけ含める必要があるというルールがあります。

違う

const para = (
    <p></p>
    <p></p>
);

正しい

const para = (
    <div>
        <p></p>
        <p></p>
    </div>
);

1

React 16は戻り値を配列として取得するため、divのような1つの要素でラップする必要があります。

間違ったアプローチ

render(){
    return(
    <input type="text" value="" onChange={this.handleChange} />

     <button className="btn btn-primary" onClick=   {()=>this.addTodo(this.state.value)}>Submit</button>

    );
}

適切なアプローチ(1つのdiv内のすべての要素または使用している他の要素)

render(){
    return(
        <div>
            <input type="text" value="" onChange={this.handleChange} />

            <button className="btn btn-primary" onClick={()=>this.addTodo(this.state.value)}>Submit</button>
        </div>
    );
}

1

Reactコンポーネントは単一のコンテナーにラップする必要があります。 たとえば "<div> .. </ div>"ます。

ReactCSSTransitionGroupのrenderメソッドを確認できます


0

ビューをインポートしてラップしViewます。のラッピングはdivうまくいきませんでした。

import { View } from 'react-native';
...
    render() {
      return (
        <View>
          <h1>foo</h1>
          <h2>bar</h2>
        </View>
      );
    }

2
これは、react nativeを使用しているためです。
Nick H247

また、フラグメントはReact Nativeでも使用できるため、a Viewは実際には最良のソリューションではありません。
Emile Bergeron

0

無効: 子要素だけでなく

render(){
        return(
            <h2>Responsive Form</h2>
            <div>Adjacent JSX elements must be wrapped in an enclosing tag</div>
            <div className="col-sm-4 offset-sm-4">
                <form id="contact-form" onSubmit={this.handleSubmit.bind(this)} method="POST">
                    <div className="form-group">
                        <label for="name">Name</label>
                        <input type="text" className="form-control" id="name" />
                    </div>
                    <div className="form-group">
                        <label for="exampleInputEmail1">Email address</label>
                        <input type="email" className="form-control" id="email" aria-describedby="emailHelp" />
                    </div>
                    <div className="form-group">
                        <label for="message">Message</label>
                        <textarea className="form-control" rows="5" id="message"></textarea>
                    </div>
                    <button type="submit" className="btn btn-primary">Submit</button>
                </form>
            </div>
        )
    }

有効: 子要素の下のルート要素

render(){
        return(
          <div>
            <h2>Responsive Form</h2>
            <div>Adjacent JSX elements must be wrapped in an enclosing tag</div>
            <div className="col-sm-4 offset-sm-4">
                <form id="contact-form" onSubmit={this.handleSubmit.bind(this)} method="POST">
                    <div className="form-group">
                        <label for="name">Name</label>
                        <input type="text" className="form-control" id="name" />
                    </div>
                    <div className="form-group">
                        <label for="exampleInputEmail1">Email address</label>
                        <input type="email" className="form-control" id="email" aria-describedby="emailHelp" />
                    </div>
                    <div className="form-group">
                        <label for="message">Message</label>
                        <textarea className="form-control" rows="5" id="message"></textarea>
                    </div>
                    <button type="submit" className="btn btn-primary">Submit</button>
                </form>
            </div>
          </div>
        )
    }

「私も」タイプの答えを避けるか、あなたがする、関連する何かを持っていない限り、同じ溶液を繰り返してください追加し、それには。
エミールベルジェロン

-1

Rect-Native開発者向け。FlatListのrenderingItemでこのエラーが発生しました。2つのTextコンポーネントがありました。以下のように使っていました

renderItem = { ({item}) => 
     <Text style = {styles.item}>{item.key}</Text>
     <Text style = {styles.item}>{item.user}</Text>
}

しかし、これらの2つのインサイドビューコンポーネントを配置した後は、うまくいきました。

renderItem = { ({item}) => 
   <View style={styles.flatview}>
      <Text style = {styles.item}>{item.key}</Text>
      <Text style = {styles.item}>{item.user}</Text>
   </View>
 }

他のコンポーネントを使用している可能性がありますが、それらをビューに配置するとうまくいく場合があります。


フラグメントはReact Nativeでも使用できるため、a Viewは実際には最良のソリューションではありません。
Emile Bergeron

-1

returnステートメント内で複数のDivをネストしようとすると、問題が発生する可能性もあります。コンポーネントをブロック要素として確実にレンダリングするために、これを行うことができます。

複数のdivを使用して、いくつかのコンポーネントを正しくレンダリングする例を次に示します。

return (
  <div>
    <h1>Data Information</H1>
    <div>
      <Button type="primary">Create Data</Button>
    </div>
  </div>
)

-1

私はこのエラーを生成する問題を抱えていました。

const App = () => {
  return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
  )
}

そしてここに修正がありました...

const App = () => {
  return (
      <div className="AppClassName">       <--- note the change
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
  )
}

図を行きます。他の人がこの衝突に遭遇した場合に備えて、ここで共有される情報。どうやら、要素クラス名をそのReact親関数名と同じにすることはできません。


それは真実ではない。codesandbox Reactテンプレートのデフォルトですらあります。他の何かがこのクラス名と競合している必要があります。
エミールベルジェロン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.