解析错误:相邻的JSX元素必须包装在一个封闭的标记中

use*_*337 413 javascript render reactjs

我正在尝试设置我的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>
    )
  },
Run Code Online (Sandbox Code Playgroud)

基本上,这里的重要部分是if(this.state.submitted == false)部分(我希望在提交的变量设置为false时显示这些div).

但是在运行时,我在问题中得到错误:

未捕获的错误:解析错误:第38行:相邻的JSX元素必须包装在一个封闭的标记中

这是什么问题?我可以用什么来完成这项工作?

wda*_*xna 581

你应该把你的组件放在一个封闭的标签之间,这意味着:

// WRONG!

return (  
    <Comp1 />
    <Comp2 />
)
Run Code Online (Sandbox Code Playgroud)

代替:

// Correct

return (
    <div>
       <Comp1 />
       <Comp2 />
    </div>
)
Run Code Online (Sandbox Code Playgroud)

编辑: Per Joe Clay关于Fragments API的评论

// More Correct

return (
    <React.Fragment>
       <Comp1 />
       <Comp2 />
    </React.Fragment>
)
Run Code Online (Sandbox Code Playgroud)

  • 由于此问题/答案目前是此错误消息的Google最高结果,因此我想指出React已经添加了[Fragments API](https://reactjs.org/docs/fragments.html),允许您在不添加额外DOM节点的情况下实现相同的功能. (57认同)
  • 如果我在表中一起打印2行怎么办?如何包装&lt;tr&gt;? (4认同)

Wit*_*ult 202

现在回答这个问题已经很晚了,但我认为这会增加解释.

这种情况正在发生,因为代码中的任何位置都会同时返回两个元素.

例如

return(
    <div id="div1"></div>
    <div id="div1"></div>
  )
Run Code Online (Sandbox Code Playgroud)

它应该包装在元素中.例如

 return(
      <div id="parent">
        <div id="div1"></div>
        <div id="div1"></div>
      </div>
      )
Run Code Online (Sandbox Code Playgroud)


更详细的说明

您的以下jsx代码会被转换

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

进入这个

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

但如果你这样做

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

这被转换成这个(仅用于说明目的,实际上你会得到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'
        )
    }
  }]);
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,您可以看到您尝试从方法调用返回两次,这显然是错误的.


Mat*_*kin 112

React元素只能返回一个元素.您必须使用另一个元素标记包装两个标记.

我还可以看到你的渲染函数没有返回任何东西.这就是你的组件应该是这样的:

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

另请注意,您不能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 />
    }
},
Run Code Online (Sandbox Code Playgroud)


Nea*_*eal 91

如果您不想像其他答案所建议的那样将其包装在另一个div中,您也可以将其包装在一个数组中并且它将起作用.

// Wrong!
return (  
   <Comp1 />
   <Comp2 />
)
Run Code Online (Sandbox Code Playgroud)

它可以写成:

// Correct!
return (  
    [<Comp1 />,
    <Comp2 />]
)
Run Code Online (Sandbox Code Playgroud)

请注意,以上内容会产生警告: 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" />]
)
Run Code Online (Sandbox Code Playgroud)

以下是有关密钥的更多信息:http://facebook.github.io/react/docs/multiple-components.html#dynamic-children

  • 我试过这个,它给了我一个错误.必须返回有效的React元素(或null).您可能已返回undefined,数组或其他一些无效对象. (7认同)
  • @prasadmsvs +1 invariant.js:39 Uncaught Invariant Violation:CommitFilter.render():必须返回有效的ReactComponent.您可能已返回undefined,数组或其他一些无效对象. (3认同)
  • 这应该是接受的答案imho. (2认同)
  • @aaaaaa由于当前React协调器的工作方式而无法实现.它是一个堆栈,并且以递归方式完成协调.在React 16中,这是固定的,您现在可以返回一个数组. (2认同)

Chr*_*ris 48

问题

解析错误:相邻的JSX元素必须包装在一个封闭的标记中

这意味着您尝试以不正确的方式返回多个兄弟JSX元素.请记住,您不是在编写HTML,而是在编写JSX!您的代码从JSX转换为JavaScript.例如:

render() {
  return (<p>foo bar</p>);
}
Run Code Online (Sandbox Code Playgroud)

将被翻译成:

render() {
  return React.createElement("p", null, "foo bar");
}
Run Code Online (Sandbox Code Playgroud)

除非您是一般的编程新手,否则您已经知道(任何语言的)函数/方法可以使用任意数量的参数,但始终只返回一个值.鉴于此,您可能会发现在尝试根据createElement()工作原理返回多个兄弟组件时会出现问题; 它只接受一个元素的参数并返回它.因此,我们不能从一个函数调用返回多个元素.


所以,如果你曾经想过为什么这个有用......

render() {
  return (
    <div>
      <p>foo</p>
      <p>bar</p>
      <p>baz</p>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

但不是这个......

render() {
  return (
    <p>foo</p>
    <p>bar</p>
    <p>baz</p>
  );
}
Run Code Online (Sandbox Code Playgroud)

这是因为在第一个片段,无论是<p>-elements是部分children的中<div>-元素.当他们成为children我们的一部分时,我们可以表达无限数量的兄弟元素.看看这会如何变化:

render() {
  return React.createElement(
    "div",
    null,
    React.createElement("p", null, "foo"),
    React.createElement("p", null, "bar"),
    React.createElement("p", null, "baz"),
  );
}
Run Code Online (Sandbox Code Playgroud)

解决方案

根据您运行的React版本,您可以使用以下几个选项来解决此问题:

  • 使用片段(仅限React v16.2 +!)

    从React v16.2开始,React支持Fragments,Fragments是一个无节点组件,可直接返回其子节点.

    返回数组中的子节点(见下文)有一些缺点:

    • 数组中的子项必须以逗号分隔.
    • 数组中的子节点必须有一个键来阻止React的键警告.
    • 字符串必须用引号括起来.

    这些从片段的使用中消除.这是一个包裹在片段中的孩子的例子:

    render() {
      return (
        <>
          <ChildA />
          <ChildB />
          <ChildC />
        </>
      );
    }
    
    Run Code Online (Sandbox Code Playgroud)

    脱糖成:

    render() {
      return (
        <React.Fragment>
          <ChildA />
          <ChildB />
          <ChildC />
        </React.Fragment>
      );
    }
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,第一个代码段需要Babel v7.0或更高版本.


  • 返回一个数组(仅限React v16.0 +!)

    从React v16开始,React Components可以返回数组.这与早期版本的React不同,在早期版本的React中,您必须将所有同级组件包装在父组件中.

    换句话说,您现在可以:

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

    这转化为:

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

    请注意,上面返回一个数组.从React版本16及更高版本开始,数组是有效的React Elements.对于早期版本的React,数组不是有效的返回对象!

    另请注意,以下内容无效(您必须返回一个数组):

    render() {
      return (<p>foo</p> <p>bar</p>);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 将元素包装在父元素中

    另一个解决方案涉及创建一个父组件,它将兄弟组件包装在其中children.这是解决此问题的最常用方法,适用于所有版本的React.

    render() {
      return (
        <div>
          <h1>foo</h1>
          <h2>bar</h2>
        </div>
      );
    }
    
    Run Code Online (Sandbox Code Playgroud)

    注意:请再次查看此答案的顶部以获取更多详细信息以及如何进行此操作.


Mor*_*s S 21

React 16.0.0我们可以将render中的多个组件作为数组返回.

return ([
    <Comp1 />,
    <Comp2 />
]);
Run Code Online (Sandbox Code Playgroud)

React 16.4.0我们可以在Fragment标签中从render返回多个组件.分段

return (
<React.Fragment>
    <Comp1 />
    <Comp2 />
</React.Fragment>);
Run Code Online (Sandbox Code Playgroud)

Future React你将能够使用这种速记语法.(许多工具尚不支持它,因此您可能希望<Fragment>在工具赶上之前明确写入.)

return (
<>
    <Comp1 />
    <Comp2 />
</>)
Run Code Online (Sandbox Code Playgroud)

  • 如果你正在解构 `import React { Fragment } from 'react';` 那么你可以像这样使用它 `&lt;Fragment &gt;` (2认同)

小智 8

如果不包装组件,则可以按以下方法编写。

代替:

return(
  <Comp1 />
  <Comp2 />
     );
Run Code Online (Sandbox Code Playgroud)

你可以这样写:

return[(
 <Comp1 />
),
(
<Comp2 />
) ];
Run Code Online (Sandbox Code Playgroud)


小智 5

非常简单,我们可以使用父元素div来包装所有元素,也可以使用高阶组件(HOC's)概念,即对react js应用程序非常有用

render() {
  return (
    <div>
      <div>foo</div>
      <div>bar</div>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

或另一种最佳方法是HOC,它非常简单而不是非常复杂,只需在您的项目中添加文件hoc.js并简单地添加这些代码

const aux = (props) => props.children;
export default aux;
Run Code Online (Sandbox Code Playgroud)

现在,将hoc.js文件导入到要使用的位置,而不是使用div元素包装,而可以使用hoc包装。

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

    render() {
      return (
    <Hoc>
        <div>foo</div>
        <div>bar</div>
    </Hoc>
      );
    }
Run Code Online (Sandbox Code Playgroud)