Ошибка анализа. Смежные элементы JSX должны быть завернуты в тег

Я пытаюсь настроить приложение 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).

Но при запуске этого я получаю ошибку в вопросе:

Uncaught Error: Parse Error: Строка 38: Соседние элементы JSX должны быть заключены в тег

В чем здесь проблема? И что я могу использовать, чтобы сделать эту работу?

Ответ 1

Вы должны поместить свой компонент между тегом, который означает:

// WRONG!

return (  
    <Comp1 />
    <Comp2 />
)

Вместо:

// Correct

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

Редактировать: Per Joe Clay комментарий об API фрагментов

// More Correct

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

Ответ 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'
        )
    }
  }]);

В приведенном выше коде вы можете видеть, что вы пытаетесь дважды вернуться из вызова метода, что, очевидно, неправильно.

Edit- Последние изменения в Реакте 16 и подопечных:

Если вы не хотите добавлять дополнительный div для переноса и хотите возвращать больше, чем для дочерних компонентов, вы можете использовать React.Fragments.

React.Fragments немного быстрее и использует меньше памяти (не нужно создавать дополнительный узел DOM, меньше загроможденного дерева DOM).

например (в Реакте 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."
 ];
}

Ответ 3

Элемент React должен возвращать только один элемент. Вам придется обернуть оба тега другим тегом элемента.

Я также вижу, что ваша функция рендеринга ничего не возвращает. Вот как должен выглядеть ваш компонент:

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

Ответ 4

Если вы не хотите заключать его в другой 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" />]
)

Вот еще немного информации о ключах:Состав против наследования

Ответ 5

Проблема

Ошибка анализа: смежные элементы JSX должны быть заключены в тег

Это означает, что вы пытаетесь вернуть несколько элементов JSX дочернего узла неверным образом. Помните, что вы не пишете HTML, а JSX! Ваш код транслируется из JSX в JavaScript. Например:

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

будет транслироваться в:

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

Если вы вообще не новичок в программировании, вы уже знаете, что функции/методы (любого языка) принимают любое количество параметров, но всегда возвращают только одно значение. Учитывая это, вы, вероятно, увидите, что возникает проблема при попытке вернуть несколько компонентов sibling на основе того, как работает createElement(); он принимает только параметры для элемента один и возвращает это. Следовательно, мы не можем возвращать несколько элементов из одного вызова функции.


Итак, если вы когда-нибудь задумывались, почему это работает...

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> -элементы являются частью 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 поддерживает Фрагменты, который является компонентом node без возврата, который возвращает своих детей напрямую.

    Возврат дочерних элементов в массиве (см. ниже) имеет некоторые недостатки:

    • Дети в массиве должны быть разделены запятыми.
    • У детей в массиве должен быть ключ, предупреждающий клавишу Reacts.
    • Строки должны быть заключены в кавычки.

    Они исключаются из использования фрагментов. Вот пример детей, завернутых в фрагмент:

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

    который de-sugars в:

    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 массивы недействительны возвращаемым объектам!

    Также обратите внимание, что следующее недействительно (вы должны вернуть массив):

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

  • Оберните элементы в родительский элемент

    Другое решение включает создание родительского компонента, который обертывает дочерние компоненты в children. Это, безусловно, самый распространенный способ решения этой проблемы и работает во всех версиях React.

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

    Примечание. Посмотрите еще раз в верхней части этого ответа для получения более подробной информации и того, как это происходит.

Ответ 6

Реагируя на 16.0.0, мы можем вернуть несколько компонентов рендеринга в виде массива.

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

Реагируя на 16.4.0, мы можем вернуть несколько компонентов рендера в теге Fragment. Фрагмент

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

Реакция на будущее вы сможете использовать этот сокращенный синтаксис. (многие инструменты еще не поддерживают его, поэтому вы можете явно написать <Fragment> пока инструмент не догонит.)

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

Ответ 7

Если вы не заверните свой компонент, то вы можете написать его, как указано ниже метод.

Вместо:

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

Вы можете написать это:

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

Ответ 8

это очень просто, мы можем использовать родительский элемент div, чтобы обернуть все элементы, или мы можем использовать концепцию компонента высшего порядка (HOC), то есть очень полезно для приложений JAS реагировать

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

Ответ 9

React 16 получает ваш возврат в виде массива, поэтому он должен быть заключен в один элемент, например, div.

Неправильный подход

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

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

    );
}

Правильный подход (все элементы в одном 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>
    );
}

Ответ 10

Реактивные компоненты должны быть упакованы в один контейнер, который может быть любым тегом, например "<div>.. </div>"

Вы можете проверить метод визуализации ReactCSSTransitionGroup

Ответ 11

В реакции есть правило, что у выражения JSX должен быть ровно один самый внешний элемент.

неправильно

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

правильный

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

Ответ 12

Импортировать представление и завернуть в View. Обертка в div не работала для меня.

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

Ответ 13

Неверно: не только дочерние элементы

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

Ответ 14

Для разработчиков Rect-Native. Я сталкиваюсь с этой ошибкой при рендеринге элемента в FlatList. У меня было два текстовых компонента. Я использовал их, как показано ниже

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

Но после того, как я положил эти буксирные компоненты Inside View, это сработало для меня.

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

Возможно, вы используете другие компоненты, но их установка в View может быть вам полезна.