Parse Error: Elemen JSX yang berdekatan harus dibungkus dengan tag terlampir

467

Saya mencoba mengatur React.jsaplikasi saya sehingga hanya merender jika variabel yang saya setel adalah true.

Cara fungsi render saya diatur terlihat seperti:

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>
    )
  },

Pada dasarnya, bagian penting di sini adalah if(this.state.submitted==false)bagian (saya ingin divelemen - elemen ini muncul ketika variabel yang dikirimkan diatur ke false).

Tetapi ketika menjalankan ini, saya mendapatkan kesalahan dalam pertanyaan:

Uncaught Error: Parse Error: Line 38: Elemen JSX yang berdekatan harus dibungkus dengan tag terlampir

apa yang terjadi disini? Dan apa yang bisa saya gunakan untuk membuat ini bekerja?

pengguna1072337
sumber
3
stackoverflow.com/questions/25034994/... Orang-orang lain di sini hanya memberitahu Anda untuk menggunakan elemen induk, tetapi itu mungkin tidak perlu. Versi pertanyaan Anda yang lebih lama ini memiliki jawaban yang menarik menggunakan array.
Meow

Jawaban:

637

Anda harus meletakkan komponen Anda di antara tag penutup, yang berarti:

// WRONG!

return (  
    <Comp1 />
    <Comp2 />
)

Sebagai gantinya:

// Correct

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

Sunting: Per komentar Joe Clay tentang Fragmen API

// More Correct

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

// Short syntax

return (
    <>
       <Comp1 />
       <Comp2 />
    </>
)
wdanxna
sumber
4
Bagaimana jika saya mencetak 2 baris bersamaan dalam sebuah tabel. Bagaimana saya bisa membungkus <tr>?
Jose
235

Sudah terlambat untuk menjawab pertanyaan ini, tetapi saya pikir itu akan menambah penjelasan.

Ini terjadi karena di mana pun dalam kode Anda, Anda mengembalikan dua elemen secara bersamaan.

misalnya

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

Itu harus dibungkus dengan elemen induk . misalnya

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


Penjelasan Lebih Lengkap

jsxKode di bawah Anda ditransformasikan

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

dalam hal ini

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

Tetapi jika Anda melakukan ini

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

ini akan dikonversi menjadi ini (Hanya untuk tujuan ilustrasi, sebenarnya Anda akan mendapatkan 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'
        )
    }
  }]);

Dalam kode di atas Anda dapat melihat bahwa Anda mencoba untuk kembali dua kali dari pemanggilan metode, yang jelas salah.

Edit- Perubahan terbaru dalam Bereaksi 16 dan memiliki-bangsal sendiri:

Jika Anda tidak ingin menambahkan div tambahan untuk membungkusnya dan ingin mengembalikan lebih dari satu komponen anak, Anda dapat menggunakannya React.Fragments.

React.Fragments sedikit lebih cepat dan memiliki lebih sedikit penggunaan memori (tidak perlu membuat simpul DOM tambahan, pohon DOM kurang berantakan).

mis. (React 16.2.0)

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

atau

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

atau

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

Elemen reaksi harus mengembalikan hanya satu elemen. Anda harus membungkus kedua tag Anda dengan tag elemen lain.

Saya juga dapat melihat bahwa fungsi render Anda tidak mengembalikan apa pun. Beginilah tampilan komponen Anda:

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

Perhatikan juga bahwa Anda tidak dapat menggunakan ifpernyataan di dalam elemen yang dikembalikan:

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 />
    }
},
Matan Gubkin
sumber
ini tidak mengatasi masalah dengan "jika"; Jika saya menghapus "jika" dalam fungsi render, itu berfungsi dengan baik.
user1072337
1
Perhatikan bahwa Anda tidak dapat menggunakan statments di dalam elemen retuned. lihat jawaban saya yang diperbarui
Matan Gubkin
99

Jika Anda tidak ingin membungkusnya dengan div lain seperti yang disarankan oleh jawaban lain, Anda juga dapat membungkusnya dalam array dan itu akan berfungsi.

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

Itu dapat ditulis sebagai:

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

Harap perhatikan bahwa hal di atas akan menghasilkan peringatan: Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of 'YourComponent'.

Ini dapat diperbaiki dengan menambahkan keyatribut ke komponen, jika menambahkan secara manual ini menambahkannya seperti:

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

Berikut adalah beberapa informasi lebih lanjut tentang kunci: Komposisi vs Warisan

Neal
sumber
7
Saya mencoba ini dan itu memberi saya kesalahan. Elemen Bereaksi yang valid (atau nol) harus dikembalikan. Anda mungkin telah mengembalikan undefined, array, atau objek tidak valid lainnya.
prasadmsvs
3
@prasadmsvs +1 invariant.js: 39 Pelanggaran Invarian Tidak Tertangkap: CommitFilter.render (): ReactComponent yang valid harus dikembalikan. Anda mungkin telah mengembalikan undefined, array, atau objek tidak valid lainnya.
Svetlana Ivanova
1
Ini adalah solusi tepat untuk saat-saat di mana Anda perlu / ingin menghindari elemen pembungkus!
bloudermilk
2
@aaaaaa itu tidak mungkin karena cara React reconciler saat ini bekerja. Itu adalah tumpukan dan rekonsiliasi dilakukan secara rekursif. Di Bereaksi 16 ini sudah diperbaiki, dan Anda sekarang dapat mengembalikan array.
natnai
1
github.com/iamdustan/tiny-react-renderer adalah repositori yang luar biasa yang harus dibaca oleh setiap pengembang reaksi. Setelah Anda melakukannya, itu akan segera menjadi jelas bagi Anda mengapa pelaksanaan reaksi saat ini tidak memungkinkan pengembalian beberapa anak.
natnai
49

Masalah

Parse Error: Elemen JSX yang berdekatan harus dibungkus dengan tag terlampir

Ini berarti bahwa Anda mencoba mengembalikan beberapa elemen JSX saudara dengan cara yang salah. Ingatlah bahwa Anda tidak menulis HTML, tetapi JSX! Kode Anda diubah dari JSX ke JavaScript. Sebagai contoh:

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

akan diubah menjadi:

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

Kecuali Anda baru mengenal pemrograman pada umumnya, Anda sudah tahu bahwa fungsi / metode (dari bahasa apa pun) mengambil sejumlah parameter tetapi selalu hanya mengembalikan satu nilai. Karena itu, Anda mungkin dapat melihat bahwa masalah muncul ketika mencoba mengembalikan beberapa komponen saudara berdasarkan cara createElement()kerjanya; hanya membutuhkan parameter untuk satu elemen dan mengembalikannya. Karenanya kami tidak dapat mengembalikan beberapa elemen dari satu panggilan fungsi.


Jadi jika Anda pernah bertanya-tanya mengapa ini bekerja ...

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

tapi bukan ini ...

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

itu karena di potongan pertama, kedua <p>-elements adalah bagian dari childrendari <div>-element. Ketika mereka adalah bagian dari childrenmaka kita dapat mengekspresikan sejumlah elemen saudara. Lihatlah bagaimana ini akan transparan:

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

Solusi

Bergantung pada versi Bereaksi yang Anda jalankan, Anda memiliki beberapa opsi untuk mengatasinya:

  • Gunakan fragmen (Hanya Reaksi v16.2 +!)

    Pada React v16.2, React memiliki dukungan untuk Fragmen yang merupakan komponen tanpa node yang mengembalikan anak-anaknya secara langsung.

    Mengembalikan anak-anak dalam array (lihat di bawah) memiliki beberapa kelemahan:

    • Anak-anak dalam array harus dipisahkan dengan koma.
    • Anak-anak dalam array harus memiliki kunci untuk mencegah peringatan kunci Bereaksi.
    • String harus dibungkus dengan tanda kutip.

    Ini dihilangkan dari penggunaan fragmen. Berikut adalah contoh anak-anak yang dibungkus dalam sebuah fragmen:

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

    yang mengubah gula menjadi:

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

    Perhatikan bahwa cuplikan pertama membutuhkan Babel v7.0 atau lebih tinggi.


  • Kembalikan array (Hanya Reaksi v16.0 +!)

    Pada React v16, React Components dapat mengembalikan array. Ini tidak seperti versi React sebelumnya yang mengharuskan Anda membungkus semua komponen saudara dalam komponen induk.

    Dengan kata lain, sekarang Anda dapat melakukan:

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

    ini mentransformasikan menjadi:

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

    Perhatikan bahwa di atas mengembalikan array. Array adalah Elemen Bereaksi yang valid sejak Bereaksi versi 16 dan yang lebih baru. Untuk React versi sebelumnya, array bukanlah objek pengembalian yang valid!

    Perhatikan juga bahwa yang berikut tidak valid (Anda harus mengembalikan array):

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

  • Bungkus elemen dalam elemen induk

    Solusi lain melibatkan pembuatan komponen induk yang membungkus komponen saudara di dalamnya children. Sejauh ini, ini adalah cara paling umum untuk mengatasi masalah ini, dan berfungsi di semua versi Bereaksi.

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

    Catatan: Lihat lagi di bagian atas jawaban ini untuk detail lebih lanjut dan bagaimana hal ini transparan .

Chris
sumber
@Grievoushead, bukan untuk komponen, tidak. Hanya untuk anak-anak.
Chris
1
Bagus, masalah tetap bagi saya.
Sohan
1
Terima kasih Chris telah meluangkan waktu untuk menjelaskan solusi lain!
Marvel Moe
pada Bereaksi v16.4contoh pertama tidak bekerja menggunakan <><React.Fragment>
:,
@vsync dukungan untuk sintaks itu bervariasi pada lingkungan gedung Anda. Tidak yakin apakah babel mendukungnya, dan jika demikian, versi mana.
Chris
22

Bereaksi 16.0.0 kita dapat mengembalikan beberapa komponen dari render sebagai sebuah array.

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

Bereaksi 16.4.0 kami dapat mengembalikan beberapa komponen dari render dalam tag Fragmen. Pecahan

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

Future Bereaksi Anda akan dapat menggunakan sintaks singkatan ini. (banyak alat belum mendukungnya sehingga Anda mungkin ingin menulis secara eksplisit <Fragment>sampai alat tersebut menyusul.)

return (
<>
    <Comp1 />
    <Comp2 />
</>)
Morris S
sumber
1
Anda lupa ,antara komponen. Ini adalah array sehingga Anda perlu memisahkan setiap elemen di dalamnya.
Chris
Tidak ada <Fragment>, itu <React.Fragment>. mengatakan demikian di tautan Anda sendiri
vsync
2
Jika Anda merusak import React { Fragment } from 'react';maka Anda menggunakannya seperti ini<Fragment >
Morris S
7

Jika Anda tidak membungkus komponen Anda maka Anda dapat menulisnya seperti yang disebutkan di bawah metode ini.

Dari pada:

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

Anda dapat menulis ini:

return[(
 <Comp1 />
),
(
<Comp2 />
) ];
ronak ganatra
sumber
6

itu sangat sederhana kita dapat menggunakan div elemen induk untuk membungkus semua elemen atau kita dapat menggunakan konsep Komponen Orde Tinggi (HOC) yaitu sangat berguna untuk bereaksi aplikasi js

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

atau cara terbaik lainnya adalah HOC sangat sederhana tidak terlalu rumit cukup tambahkan file hoc.js di proyek Anda dan cukup tambahkan kode-kode ini

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

sekarang impor file hoc.js di mana Anda ingin menggunakan, sekarang alih-alih membungkus dengan elemen div kita bisa membungkus dengan hoc.

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

    render() {
      return (
    <Hoc>
        <div>foo</div>
        <div>bar</div>
    </Hoc>
      );
    }
Fazal
sumber
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang bagaimana dan / atau mengapa memecahkan masalah akan meningkatkan nilai jangka panjang jawaban. Baca ini .
Shanteshwar Inde
Fungsi yang Anda bicarakan, yaitu disebut HOC di reactjs. berarti props.children
Fazal
4

Ada aturan dalam bereaksi bahwa ekspresi JSX harus memiliki tepat satu elemen terluar.

salah

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

benar

const para = (
    <div>
        <p></p>
        <p></p>
    </div>
);
Khandelwal-manik
sumber
1

Bereaksi 16 mendapat pengembalian Anda sebagai array sehingga harus dibungkus oleh satu elemen seperti div.

Pendekatan yang Salah

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

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

    );
}

Pendekatan Benar (Semua elemen dalam satu div atau elemen lain yang Anda gunakan)

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

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

Komponen yang bereaksi harus dibungkus dalam wadah tunggal, yang mungkin berupa tag apa pun, mis. "<Div> .. </ div>"

Anda dapat memeriksa metode render ReactCSSTransitionGroup

Shivprasad P
sumber
0

Impor tampilan dan bungkus View. Membungkus dalam divtidak berhasil untuk saya.

import { View } from 'react-native';
...
    render() {
      return (
        <View>
          <h1>foo</h1>
          <h2>bar</h2>
        </View>
      );
    }
Ocko
sumber
2
Itu karena Anda menggunakan reaksi asli.
Nick H247
Dan fragmen juga tersedia di React Native, jadi a Viewbukanlah solusi yang terbaik.
Emile Bergeron
0

Tidak valid: Tidak hanya elemen anak

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>
        )
    }

Valid: Elemen root di bawah elemen anak

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>
        )
    }
KARTHIKEYAN.A
sumber
Harap hindari "saya juga" ketik jawaban atau ulangi solusi yang sama, kecuali Anda memiliki sesuatu yang relevan untuk ditambahkan .
Emile Bergeron
-1

Untuk pengembang Rect-Native. Saya mengalami kesalahan ini saat renderingItem di FlatList. Saya memiliki dua komponen Teks. Saya menggunakan mereka seperti di bawah ini

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

Tetapi setelah saya memasukkan komponen Inside View ini, itu berhasil untuk saya.

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

Anda mungkin menggunakan komponen lain tetapi memasukkannya ke dalam View mungkin berhasil untuk Anda.

Gurjinder Singh
sumber
Fragmen-fragmen juga tersedia di React Native, jadi a Viewbukanlah solusi yang terbaik.
Emile Bergeron
-1

Saya pikir komplikasi juga dapat terjadi ketika mencoba untuk bersarang beberapa Div dalam pernyataan kembali. Anda mungkin ingin melakukan ini untuk memastikan komponen Anda dirender sebagai elemen blok.

Berikut adalah contoh rendering beberapa komponen yang benar, menggunakan beberapa div.

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

Saya punya masalah yang menghasilkan kesalahan ini yang tidak semuanya jelas.

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

Dan di sini ada perbaikan ...

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

Sosok pergi. Info dibagikan di sini kalau-kalau ada orang lain yang menabrak gundukan ini. Tampaknya, Anda tidak dapat memiliki nama kelas elemen yang sama dengan nama fungsi orangtuanya yang Bereaksi.

zipzit
sumber
Itu tidak benar. Bahkan standar dalam templat codesandbox React. Sesuatu yang lain pasti bertentangan dengan nama kelas ini.
Emile Bergeron