有没有一种方法可以在React.render()函数中渲染多个React组件?

65

例如我可以这样做吗:

import React from 'react';
import PanelA from './panelA.jsx';
import PanelB from './panelB.jsx';

React.render( 
  <PanelA />
  <PanelB />, 
  document.body  
);

React会渲染到哪里:

body
   PanelA
   PanelB

目前我遇到了以下错误:

Adjacent JSX elements must be wrapped in an enclosing tag

当使用browserify和babelify进行转录时


6
不行,必须只有一个。把它们都包裹在<div>标签中。 - zerkms
2
FYI,从0.14版本开始,像这样将渲染结果放入document.body中会抛出警告(尽管许多教程都是这么做的),而应该通过id选择一个元素。https://facebook.github.io/react/blog/2015/09/10/react-v0.14-rc1.html#new-helpful-warnings - David Gilbertson
@DavidGilbertson 我现在意识到了这个警告... 不过为什么不直接用 React 创建 #app,而是使用 body -> #app 呢? - Bryan Grace
@BryanGrace,能否请您选择正确的答案? - Pavel Hasala
你好,能否请您标记正确的答案,因为当前的答案是错误的? - Pavel Hasala
对我来说不太明显的是,这个问题比所提出的问题更为普遍。它不仅会在两个组件中发生,而且如果返回的东西之一是文本,例如{myVar}<br/>仍然需要包装器。此外,在嵌套场景中也会出现,例如<p>{lines.map(line => ({line}<br/>))}</p>即使存在顶级<p>,也仍然需要一个包装器。因此,显然从JavaScript切换到嵌入式JSX时,JSX部分必须返回单个节点。请参见我的问题https://stackoverflow.com/q/75783783。 - Garret Wilson
8个回答

89
自 React v16.0 发布以来,当您位于组件内部时,可以渲染一个组件数组而无需在项周围添加额外的元素:
render() {
  return [
    <li key="one">First item</li>,
    <li key="two">Second item</li>,
    <li key="three">Third item</li>,
    <li key="four">Fourth item</li>,
  ];
}

请记得仅设置键。

更新

从16.2版本开始,您可以使用片段。

  render() {
    return (
      <React.Fragment>
        <td>Hello</td>
        <td>World</td>
      </React.Fragment>
    );
  }

简洁语法

  render() {
    return (
      <>
        <td>Hello</td>
        <td>World</td>
      </>
    );
  }

ReactDOM.render中,你仍然不能渲染多个项目,因为React需要一个根。因此,你可以在ReactDOM.render内部渲染单个组件,并在内部组件中渲染项目数组。


<> ... </>语法被称为什么?我知道我以前见过类似的东西,但就是想不起来该怎么在谷歌上搜索。 - undefined

45

React >= 16.2

自版本16.2以来,引入了<React.Fragment />(或简写为<></>),因此可以使用条件。

这是更可取的方式。

return (
    <React.Fragment>
        <h1>Page title</h1>
        <ContentComponent />
        {this.props.showFooter && (
            <footer>(c) stackoverflow</footer>
        )}
    </React.Fragment>
)

React 16

自从 React 16 版本以后,你可以在 render() 方法中返回一个组件列表。但是这种做法的弊端是你无法轻松地对渲染进行条件控制,因此需要为列表中的每个组件添加 key 属性。

return [
    <h1 key="page-title">Page</h1>,
    <ContentComponent key="content" />,
    <footer>(c)stackoverflow</footer>
]

React < 16

在旧版本的React中,您不能渲染多个组件而不将它们包装在一个封闭元素(标签、组件)中。

例如:

return (
  <article>
    <h1>title</h1>
    <meta>some meta</meta>
  </article>
)

如果你想将它们作为单一元素使用,你需要从它们中创建一个模块。


21

只需将多个组件包装在单个标签中即可。例如:

React.render(
  <div>
    <PanelA />
    <PanelB />
  </div>, 
  document.body  
);

11

在React 16之前,同一个render()中有多个顶层元素需要你将它们包裹在一个父元素内(通常是一个<div>):

render () {
  return (
    <div>
      <Thing1 />
      <Thing2 />
    </div>
  )
}

React 16引入了渲染顶级元素数组的功能(需要警告的是,它们必须都有唯一的键):

React 16引入了能够呈现顶层元素数组的能力(附带警告,它们全部必须具有唯一的键):

render () {
  return ([
    <Thing1 key='thing-1' />,
    <Thing2 key='thing-2' />
  ])
}

React 16.2 引入了 <Fragment> 元素,其与第一个示例中的 <div> 具有相同的功能,但不会在 DOM 中留下无意义的父级 <div>

import React, { Fragment } from 'react'

...

render () {
  return (
    <Fragment>
      <Thing1 />
      <Thing2 />
    </Fragment>
  )
}

有一种简写语法,但大多数工具(例如语法高亮器)尚未支持它:

import React from 'react'

...

render () {
  return (
    <>
      <Thing1 />
      <Thing2 />
    </>
  )
}

你的回答也回答了我一个类似的问题。同时,感谢您指出React中最新的元素。对于我们试图淘汰“过时”的教程和课程的人来说,这非常有帮助。 - Cheryl Velez

8
如果您想呈现多个组件,则需要将它们嵌套在一起以保持树形结构。关于此,请参阅他们的文档页面:多个组件 最终只要有一个节点处于顶层,它就可以工作。
您可以只使用一个DOM元素,如<div>
  <div>
    <PanelA />
    <PanelB />
  </div>

然而,随着您创建的应用程序变得越来越复杂,并且具有更多的相互关联组件,您可能会发现最好将子组件包装在父组件中,如下所示。
import React from 'react';
import PanelA from './panelA.jsx';
import PanelB from './panelB.jsx';

var PanelHolder = React.createClass({
  render: function() {
    return (
      <div>
        <PanelA />
        <PanelB />
      </div>
    )
  }
});

然后在您的主JS文件中,您会这样做:

import React from 'react';
import PanelHolder from './panelHolder.jsx';

React.render( 
  <PanelHolder /> 
  document.body  
);

2
你也可以这样做。
const list = [item1, item2]
const elements = (
    <div>
      {list.map(element => element)}
    </div>
  );
ReactDOM.render(elements, document.body);

1
this.propsTextBox.value = this._context.parameters.textBoxProperty.raw || "";
var elements = new Array<React.SFCElement<any>>();
elements.push(React.createElement(
                TextField, 
                this.propsTextBox
            ));
elements.push(React.createElement(
    Label, 
    this.propsLabel
));

ReactDOM.render(
    elements,  
    this._container
);

欢迎来到本站,@Arnaldo。我有一个小建议:尽管这段代码很容易理解,但简短的解释会让它更加易懂,从而更好地解决问题。 - Jeff Mergler

0
React.render( 
  <PanelA>
      <PanelB />
  </PanelA> 
  document.body  
);

1
如果您添加一些解释会更好。 - Trí Phan
1
虽然这段代码可能提供了问题的解决方案,但最好添加上为什么/如何运作的上下文。这可以帮助未来的用户学习,并将这些知识应用到他们自己的代码中。当代码被解释时,您还可能会得到用户的积极反馈,例如点赞。 - borchvm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接