Ayrıştırma Hatası: Bitişik JSX öğeleri bir kapalı etikete sarılmalıdır


467

Benim kurmaya çalışıyorum React.jsdeğişken ı kümesidir varsa sadece böylece render uygulaması true.

Oluşturma işlevimin ayarlanma şekli şuna benzer:

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

Temel olarak, buradaki önemli kısım if(this.state.submitted==false)kısımdır ( divGönderilen değişken ayarlandığında bu öğelerin görünmesini istiyorum false).

Ama bunu çalıştırırken, sorudaki hatayı alıyorum:

Yakalanmayan Hata: Ayrıştırma Hatası: Satır 38: Bitişik JSX öğeleri bir kapalı etikete sarılmalıdır

Burada sorun nedir? Ve bu işi yapmak için ne kullanabilirim?


3
stackoverflow.com/questions/25034994/… Buradaki diğer insanlar size yalnızca bir üst öğe kullanmanızı söylüyorlar, ancak bu gereksiz olabilir. Sorunuzun bu eski sürümü dizileri kullanarak ilginç bir yanıta sahip.
Miyav

Yanıtlar:


637

Bileşeninizi bir kapalı etiket arasına koymalısınız. Bu, şu anlama gelir:

// WRONG!

return (  
    <Comp1 />
    <Comp2 />
)

Yerine:

// Correct

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

Edit: Per Joe Clay'un Fragments API'sı hakkındaki yorumu

// More Correct

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

// Short syntax

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

4
Tabloda birlikte 2 satır yazdırıyorsam ne olur? <tr> nasıl sarabilirim?
Jose

235

Bu soruyu cevaplamak için geç ama açıklamaya ekleyeceğini düşündüm.

Bu, kodunuzdaki herhangi bir yerde aynı anda iki öğe döndürdüğünüz için oluyor.

Örneğin

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

Bir üst öğeye sarılmalıdır . Örneğin

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


Daha Ayrıntılı Açıklama

Aşağıdaki jsxkodunuz dönüştürüldü

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

bunun içine

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

Ama bunu yaparsan

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

bu dönüştürülür (Sadece gösterim amacıyla, aslında alacaksınız 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'
        )
    }
  }]);

Yukarıdaki kodda , bir yöntem çağrısından iki kez geri dönmeye çalıştığınızı görebilirsiniz , ki bu yanlıştır.

Düzenleme - React 16 ve kendi servislerinde son değişiklikler:

Eğer etrafa sarmak için ekstra div eklemek istemiyorsanız ve birden fazla alt bileşen geri dönmek istiyorsanız React.Fragments.

React.Fragments biraz daha hızlıdır ve daha az bellek kullanımına sahiptir (fazladan bir DOM düğümü, daha az dağınık DOM ağacı oluşturmaya gerek yoktur).

örneğin (Reaksiyon 16.2.0'da)

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

veya

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

veya

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

115

Reaksiyon elemanı sadece bir eleman döndürmelidir. Her iki etiketinizi de başka bir öğe etiketiyle sarmanız gerekir.

Ayrıca, oluşturma işlevinizin hiçbir şey döndürmediğini de görebiliyorum. Bileşeniniz şöyle görünmelidir:

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

Ayrıca if, döndürülen bir öğenin içindeki ifadeleri kullanamayacağınızı unutmayın :

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

bu, "if" ile ilgili sorunu gidermez; Oluşturma işlevi içindeki "if" öğesini kaldırırsam iyi çalışır.
user1072337

1
geri alınan bir öğenin içindeki ifadeleri kullanamayacağınızı unutmayın. benim güncellenmiş cevabım bak
Matan Gubkin

99

Diğer yanıtların önerdiği gibi başka bir div'e sarmak istemiyorsanız, bir diziye de sarabilirsiniz ve çalışır.

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

Şu şekilde yazılabilir:

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

Yukarıdakilerin bir uyarı oluşturacağını lütfen unutmayın: Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of 'YourComponent'.

Bu key, bileşenlere bir öznitelik eklenerek düzeltilebilir , eğer bunları manuel olarak eklerseniz aşağıdaki gibi ekleyin:

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

Anahtarlar hakkında daha fazla bilgi: Composition vs Inheritance


7
Bunu denedim ve bana bir hata veriyor. Geçerli bir React öğesi (veya null) döndürülmelidir. Undefined, bir dizi veya başka bir geçersiz nesne döndürmüş olabilirsiniz.
prasadmsvs

3
@prasadmsvs +1 invariant.js: 39 Yakalanmamış Değişmez İhlal: CommissionFilter.render (): Geçerli bir ReactComponent döndürülmelidir. Undefined, bir dizi veya başka bir geçersiz nesne döndürmüş olabilirsiniz.
Svetlana Ivanova

1
Bu, bir sargı elemanına ihtiyaç duyduğunuz / kaçınmak istediğiniz zamanlar için harika bir çözümdür!
bloudermilk

2
@aaaaaa mevcut React reconciler'in çalışması nedeniyle mümkün değil. Bu bir yığın ve mutabakat tekrar tekrar yapılır. React 16'da bu düzeltildi ve artık bir dizi döndürebilirsiniz.
natnai

1
github.com/iamdustan/tiny-react-renderer , her tepki geliştiricinin okuması gereken mükemmel bir havuzdur. Bunu yaptıktan sonra, mevcut reaksiyon uygulamasının neden birden fazla çocuğa geri dönmesine izin vermediği hemen anlaşılmalıdır.
natnai

49

Sorun

Ayrıştırma Hatası: Bitişik JSX öğeleri bir kapalı etikete sarılmalıdır

Bu, birden çok kardeş JSX öğesini yanlış bir şekilde döndürmeye çalıştığınız anlamına gelir. HTML değil JSX yazdığınızı unutmayın! Kodunuz JSX'ten JavaScript'e aktarılır. Örneğin:

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

aktarılacak:

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

Genel olarak programlama konusunda yeni değilseniz, fonksiyonların / yöntemlerin (herhangi bir dilde) herhangi bir sayıda parametre aldığını zaten biliyorsunuz, ancak her zaman sadece bir değer döndürüyoruz. Bununla birlikte, muhtemelen nasıl createElement()çalıştığına bağlı olarak birden çok kardeş bileşen döndürmeye çalışırken bir sorunun ortaya çıktığını görebilirsiniz ; yalnızca bir öğe için parametreler alır ve bunu döndürür. Bu nedenle, bir işlev çağrısından birden çok öğe döndüremeyiz.


Bunun neden işe yaradığını merak ettiyseniz ...

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

ama bu değil ...

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

İlk parçada hem yüzünden olduğunu <p>-elemanları parçası olan childrenbir <div>-eleman. Bir parçası olduklarında, childrensınırsız sayıda kardeş öğeyi ifade edebiliriz. Bunun nasıl yayılacağına bir bakın:

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

Çözümler

Hangi React sürümünü kullandığınıza bağlı olarak, bunu ele almak için birkaç seçeneğiniz vardır:

  • Parça kullanın (yalnızca React v16.2 +!)

    React v16.2'den itibaren React , çocuklarını doğrudan döndüren düğümsüz bir bileşen olan Fragments için desteğe sahiptir .

    Bir dizideki alt öğelerin döndürülmesinin (aşağıya bakın) bazı dezavantajları vardır:

    • Bir dizideki çocuklar virgülle ayrılmalıdır.
    • Bir dizideki çocukların React'ın anahtar uyarısını önlemek için bir anahtarı olmalıdır.
    • Dizeler tırnak içine alınmalıdır.

    Bunlar parçaların kullanımından çıkarılır. İşte bir parçaya sarılmış çocuklara bir örnek:

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

    hangi şekerler:

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

    İlk snippet'in Babel v7.0 veya üstünü gerektirdiğini unutmayın.


  • Bir dizi döndürme (yalnızca React v16.0 +!)

    React v16 itibariyle, React Components dizileri döndürebilir. Bu, ana bileşendeki tüm kardeş bileşenleri sarmak zorunda kaldığınız React'in önceki sürümlerinden farklıdır.

    Başka bir deyişle, artık şunları yapabilirsiniz:

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

    bu şuraya aktarılır:

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

    Yukarıdakilerin bir dizi döndürdüğünü unutmayın. Diziler, React sürüm 16 ve sonrası için geçerli React Elements'tir. React'ın önceki sürümlerinde, diziler geçerli dönüş nesneleri değildir!

    Ayrıca aşağıdakilerin geçersiz olduğunu unutmayın (bir dizi döndürmeniz gerekir):

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

  • Öğeleri bir üst öğeye sarma

    Diğer çözüm, kardeş bileşenlerini içine saran bir ana bileşen oluşturmayı içerir children. Bu, bu sorunu ele almanın en yaygın yoludur ve React'in tüm sürümlerinde çalışır.

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

    Not: Daha fazla ayrıntı ve bunun nasıl aktarılacağı hakkında bu cevabın üst kısmına tekrar bakın .


@Grievoushead, bileşenler için değil, hayır. Sadece çocuklar için.
Chris

1
Güzel bir sorun, benim için sorun çözüldü.
Sohan

1
Diğer çözümleri açıklamak için zaman ayırdığınız için teşekkürler Chris!
Marvel Moe

React v16.4üzerinde ilk örnek kullanarak çalışmaz:, <>sadece <React.Fragment>:(
vsync

@vsync sözdizimi desteği yapı ortamınıza göre değişir. Babil'in henüz destekleyip desteklemediğinden ve öyleyse hangi sürümü desteklediğinden emin değilim.
Chris

22

React 16.0.0 , render'dan çoklu bileşenleri bir dizi olarak döndürebiliriz.

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

React 16.4.0 , bir Fragment etiketindeki oluşturma işleminden birden fazla bileşen döndürebiliriz. fragman

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

Gelecek Tepki bu steno sözdizimini kullanabileceksiniz. (birçok araç henüz desteklememektedir, bu nedenle <Fragment>takım yakalanana kadar açıkça yazmak isteyebilirsiniz .)

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

1
,Bileşenler arasında bir unuttun . Bu bir dizidir, bu yüzden içindeki her öğeyi ayırmanız gerekir.
Chris

Hayır <Fragment>, yok <React.Fragment>. kendi bağlantınızda böyle diyor
vsync

2
Yıkıcı import React { Fragment } from 'react';iseniz o zaman böyle kullanın<Fragment >
Morris S

7

Bileşeninizi sarmazsanız, aşağıdaki yöntemde belirtildiği gibi yazabilirsiniz.

Onun yerine:

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

bunu yazabilirsiniz:

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

6

tüm öğeyi sarmak için bir üst öğe div'i kullanabiliriz veya Yüksek Sipariş Bileşeni (HOC'ler) konseptini kullanabiliriz, yani tepki js uygulamaları için çok yararlıdır

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

ya da başka bir en iyi yol HOC çok basit değil çok karmaşık değil sadece projenize hoc.js bir dosya ekleyin ve sadece bu kodları ekleyin

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

şimdi kullanmak istediğiniz hoc.js dosyasını içe aktarın, şimdi div elemanı ile sarmak yerine hoc ile sarabiliriz.

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

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

Bu kod soruyu cevaplayabilirken, sorunun nasıl ve / veya neden çözüldüğüne dair ek bağlam sağlamak yanıtlayıcının uzun vadeli değerini artıracaktır. Bunu okuyun .
Shanteshwar Gerçekten

Bahsettiğiniz işlevsellik, yani reaktiflerde HOC denir. sahne anlamına gelir. çocuklar
Fazal

4

Reaksiyonda bir JSX ifadesinin tam olarak en dıştaki bir öğeye sahip olması gerektiğine dair bir kural vardır.

yanlış

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

doğru

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

1

React 16, dönüşünüzü bir dizi olarak alır, bu nedenle div gibi bir öğe tarafından sarılmalıdır.

Yanlış Yaklaşım

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

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

    );
}

Doğru Yaklaşım (Bir div'deki veya kullandığınız diğer bir öğedeki tüm öğeler)

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

Reaksiyon bileşenleri tek bir kapta sarılmalıdır, bu herhangi bir etiket olabilir, örneğin "<div> .. </ div>"

ReactCSSTransitionGroup'un oluşturma yöntemini kontrol edebilirsiniz


0

Görünümü içe aktarın ve sarın View. Bir sarma divbenim için işe yaramadı.

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

2
çünkü yerli tepki kullanıyorsunuz.
Nick H247

Ve React Native'de parçalar da mevcuttur, bu yüzden a Viewgerçekten en iyi çözüm değildir.
Emile Bergeron

0

Geçersiz: Yalnızca alt öğeler değil

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

Geçerli: Alt öğelerin altındaki kök öğe

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

Ekleyeceğiniz bir şey yoksa, lütfen "ben de" türü yanıtlardan veya aynı çözümü tekrar etmekten kaçının .
Emile Bergeron

-1

Rect-Native geliştiricileri için. FlatList'te renderingItem yaparken bu hatayla karşılaşıyorum. İki Metin bileşenim vardı. Onları aşağıdaki gibi kullanıyordum

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

Ama ben bu yedek Inside View Bileşenleri koyduktan sonra benim için çalıştı.

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

Başka bileşenler kullanıyor olabilirsiniz, ancak bunları Görünüme koymak sizin için yararlı olabilir.


Parçalar React Native'de de mevcuttur, bu yüzden a Viewgerçekten en iyi çözüm değildir.
Emile Bergeron

-1

Ben de komplikasyon dönüş ifadesi içinde birden fazla Div yuvalama çalışırken ortaya çıkabilir düşünüyorum. Bileşenlerinizin blok öğeleri olarak oluşturulmasını sağlamak için bunu yapmak isteyebilirsiniz.

Birden fazla div kullanarak birkaç bileşeni doğru şekilde oluşturmaya bir örnek.

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

-1

Hep birlikte belli değildi bu hatayı üreten bir sorun vardı.

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

Ve düzeltme buradaydı ...

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

Git şekil. Başkalarının bu yumruya çarpması durumunda bilgi burada paylaşıldı. Görünüşe göre, React üst işlev adıyla aynı öğe sınıfı adına sahip olamazsınız.


Bu doğru değil. Hatta kodandbox React şablonunda varsayılan değerdir. Başka bir şey bu sınıf adıyla çakışmış olmalıdır.
Emile Bergeron
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.