我正在尝试设置我的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)部分(我希望在提交的变量设置为false时显示这些div)。
但是在运行时,我在问题中得到错误:
未捕获错误:解析错误:第38行:相邻的JSX元素必须包装在一个封闭的标记中
这是什么问题?我可以用什么来完成这项工作?
答案 0 :(得分:520)
您应该将您的组件放在一个封闭的标签之间,这意味着:
// WRONG!
return (
<Comp1 />
<Comp2 />
)
相反:
// Correct
return (
<div>
<Comp1 />
<Comp2 />
</div>
)
编辑:Per Joe Clay关于Fragments API
的评论// More Correct
return (
<React.Fragment>
<Comp1 />
<Comp2 />
</React.Fragment>
)
答案 1 :(得分:180)
回答这个问题已经很晚了,但我认为这会增加解释。
这种情况正在发生,因为您的代码中的任何位置都会同时返回两个元素。
e.g
return(
<div id="div1"></div>
<div id="div1"></div>
)
它应该包含在父元素中。 e.g
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'
)
}
}]);
在上面的代码中,您可以看到您尝试从方法调用返回两次,这显然是错误的。
编辑 - 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."
];
}
答案 2 :(得分:103)
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 />
}
},
答案 3 :(得分:83)
如果您不想像其他答案所建议的那样将其包装在另一个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" />]
)
以下是有关密钥的更多信息:http://facebook.github.io/react/docs/multiple-components.html#dynamic-children
答案 4 :(得分:48)
解析错误:相邻的JSX元素必须包装在一个封闭的标记
中
这意味着您尝试以不正确的方式返回多个兄弟JSX元素。请记住,您不是在编写HTML,而是在编写JSX!您的代码从JSX转换为JavaScript。例如:
render() {
return (<p>foo bar</p>);
}
将被翻译成:
render() {
return React.createElement("p", null, "foo bar");
}
除非您不熟悉编程,否则您已经知道(任何语言的)函数/方法都可以使用任意数量的参数,但始终只返回一个值。鉴于此,您可能会发现在尝试根据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支持 Fragments ,它是一个无节点的组件,可直接返回其子节点。
返回数组中的子节点(见下文)有一些缺点:
- 数组中的子项必须用逗号分隔。
- 数组中的子项必须有一个键才能阻止React的键警告。
- 字符串必须用引号括起来。
从片段的使用中消除了这些。这是一个包裹在片段中的孩子的例子:
render() {
return (
<>
<ChildA />
<ChildB />
<ChildC />
</>
);
}
脱糖成:
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
请注意,第一个代码段需要Babel v7.0或更高版本。
从React v16开始,React Components可以返回数组。这与早期版本的React不同,在早期版本的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 Elements。对于早期版本的React,数组不是有效的返回对象!
另请注意,以下是无效(您必须返回一个数组):
render() {
return (<p>foo</p> <p>bar</p>);
}
另一个解决方案涉及创建一个父组件,它将兄弟组件包装在其children
中。这是解决此问题的最常用方法,适用于所有版本的React。
render() {
return (
<div>
<h1>foo</h1>
<h2>bar</h2>
</div>
);
}
注意:请再次查看此答案的顶部以获取更多详细信息以及如何转换。
答案 5 :(得分:21)
React 16.0.0 我们可以将多个组件从render返回为数组。
return ([
<Comp1 />,
<Comp2 />
]);
React 16.4.0 我们可以在Fragment标记中从render返回多个组件。 Fragment
return (
<React.Fragment>
<Comp1 />
<Comp2 />
</React.Fragment>);
Future React 您将能够使用此简写语法。 (许多工具尚不支持它,因此您可能希望明确写入<Fragment>
,直到工具赶上。)
return (
<>
<Comp1 />
<Comp2 />
</>)
答案 6 :(得分:5)
如果不包装组件,则可以按照以下方法编写。
代替:
return(
<Comp1 />
<Comp2 />
);
您可以这样写:
return[(
<Comp1 />
),
(
<Comp2 />
) ];
答案 7 :(得分:2)
第16号反应会将您的返回结果作为数组包含在其中,因此应该用div这样的一个元素包装。
错误的方法
render(){
return(
<input type="text" value="" onChange={this.handleChange} />
<button className="btn btn-primary" onClick= {()=>this.addTodo(this.state.value)}>Submit</button>
);
}
正确的方法(一格或您正在使用的其他元素中的所有元素)
render(){
return(
<div>
<input type="text" value="" onChange={this.handleChange} />
<button className="btn btn-primary" onClick={()=>this.addTodo(this.state.value)}>Submit</button>
</div>
);
}
答案 8 :(得分:2)
反应组件必须包装在单个容器中,该容器可以是任何标签
例如“
您可以检查ReactCSSTransitionGroup的呈现方法
答案 9 :(得分:2)
有一个反应规则,即JSX表达式必须恰好具有一个最外面的元素。
错误
const para = (
<p></p>
<p></p>
);
正确
const para = (
<div>
<p></p>
<p></p>
</div>
);
答案 10 :(得分:2)
非常简单,我们可以使用父元素div包装所有元素 或者我们可以使用高阶分量(HOC's)概念,即对于 反应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>
);
}
答案 11 :(得分:1)
导入视图并换入View
。包裹div
对我来说不起作用。
import { View } from 'react-native';
...
render() {
return (
<View>
<h1>foo</h1>
<h2>bar</h2>
</View>
);
}
答案 12 :(得分:1)
无效: 不仅子元素
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>
)
}
答案 13 :(得分:0)
面向Rect-Native开发人员。 FlatList中的renderItem时遇到此错误。我有两个文本组件。我正在像下面那样使用它们
renderItem = { ({item}) =>
<Text style = {styles.item}>{item.key}</Text>
<Text style = {styles.item}>{item.user}</Text>
}
但是在将这些拖曳放入View View Components之后,它对我有用。
renderItem = { ({item}) =>
<View style={styles.flatview}>
<Text style = {styles.item}>{item.key}</Text>
<Text style = {styles.item}>{item.user}</Text>
</View>
}
您可能正在使用其他组件,但将它们放入View可能对您有用。
答案 14 :(得分:0)
只需添加
<>
// code ....
</>
答案 15 :(得分:-1)
我认为,当尝试在return语句中嵌套多个Div时,也可能会出现复杂情况。您可能希望这样做,以确保您的组件呈现为块元素。
这是一个使用多个div正确渲染几个组件的示例。
return (
<div>
<h1>Data Information</H1>
<div>
<Button type="primary">Create Data</Button>
</div>
</div>
)