如何在React中的另一个return语句中返回多行JSX?


100

单行工作正常

render: function () {
  return (
    {[1,2,3].map(function (n) {
      return <p>{n}</p>
    }}
  );
}

不适用于多行

render: function () {
  return (
    {[1,2,3].map(function (n) {
      return (
        <h3>Item {n}</h3>
        <p>Description {n}</p>
      )
    }}
  );
}

谢谢。


1
有关此特定问题的详细信息:github.com/facebook/react/issues/2127
加锁存

不是return ("asdf" "asdf");您想要的return ["asdf", "asdf"];
-neaumusic

Answers:


149

尝试将标签视为函数调用(请参阅docs)。然后第一个变为:

{[1,2,3].map(function (n) {
  return React.DOM.p(...);
})}

第二个:

{[1,2,3].map(function (n) {
  return (
    React.DOM.h3(...)
    React.DOM.p(...)
  )
})}

现在应该清楚,第二个片段实际上没有任何意义(在JS中不能返回多个值)。您必须将其包装在另一个元素中(很可能是您想要的,这样您还可以提供一个有效的key属性),或者可以使用如下所示的内容:

{[1,2,3].map(function (n) {
  return ([
    React.DOM.h3(...),
    React.DOM.p(...)
  ]);
})}

使用JSX糖:

{[1,2,3].map(function (n) {
  return ([
    <h3></h3>, // note the comma
    <p></p>
  ]);
})}

您不需要展平结果数组,React会为您完成。请参阅以下提琴http://jsfiddle.net/mEB2V/1/。再说一遍:从长远来看,将这两个元素包装到div / section中将很可能更好。


4
没错实际上明确记载facebook.github.io/react/tips/...
肖恩-

1
使用return([...])但不使用flatten位可以使我完全按照我的意愿进行标记,尽管返回的数组不一定必须是flattened的,但在我特定的情况下,它不会影响最终输出。还是?
肖恩

谢谢!瓷砖!更新我的答案以包括一个指向JSFiddle的链接,该链接显示flatten是可选的。还将包括指向React文档的链接。
Jan Olaf Krems 2014年

13
这不再起作用(自0.9ish起)Uncaught Error: Invariant Violation: Product.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.
dogmatic69

2
@TimFletcher可以将数组作为渲染组件的一部分返回,例如<div>{ this.props.foos.map(function() { return <Foo /> }) }</div>。但是render组件的功能不能返回该数组而不将其包装,例如在div中。
亨里克N

35

似乎有关返回数组的旧答案不再适用(也许是由于React〜0.9,如@ dogmatic69在评论中所写)。

文档说您需要返回一个节点:

JSX根节点的最大数量

当前,在组件的渲染中,您只能返回一个节点。如果您有要返回的div列表,则必须将组件包装在div,span或任何其他组件中。

不要忘记JSX可以编译为常规JS。返回两个函数实际上并没有语法意义。同样,不要在一个三元以上放置一个以上的孩子。

在许多情况下,您只需将东西包装在a <div>或a中<span>

就我而言,我想返回多个<tr>。我将它们包裹在一个<tbody>桌子中-允许它具有多个主体。

编辑:从React 16.0开始,只要每个元素都有一个keyhttps ://facebook.github.io/react/blog/2017/09/26/react-v16.0.html,显然再次允许返回数组#new-render-return-types片段和字符串

编辑:React 16.2允许您使用<Fragment>…</Fragment>甚至包围元素列表<>…</>,如果您更喜欢数组:https : //blog.jmes.tech/react-fragment-and-semantic-html/


3
如果要返回多个,该<li>怎么办?假设我不能把所有内容都包起来<ul>
Banjocat

@Banjocat恐怕我不知道:/您被允许嵌套列表,所以<li><ul><li>one</li><li>two</li></ul></li>如果您的情况适合,您可以返回类似的内容。或者:包装div严格来说不是有效的,但是在所有相关的浏览器中都可以正常显示吗?如果您尝试尝试,请告诉我们。
亨里克N

1
@Banjocat ...我很想知道一个更好的答案给你。也许您应该把它摆成一个常规的stackoverflow问题,看看是否得到不同的答案。
user1175849 2015年

@ user1175849也许可以然后发布该问题:)
Henrik N

1
@HenrikN FWIW,包装一的“子集” li中的一个spandiv没有为我工作。div严重破坏了渲染,至少在我的用例中,该范围弄乱了CSS。2分:尝试返回lis的几个子集是一种代码味道。我们使用a ul作为一种下拉菜单,最初我希望许多组件返回lis的“部分” 。最后,最好将所有菜单代码放入“锚定”的单个组件中,而ul不是li从多个来源中拔出鞋拔子。我认为这也使UI的心理模型更加简洁。
鲁芬

13

React v16.0.0起,可以通过将多个元素包装在Array

render() {
  return (
    {[1,2,3].map(function (n) {
      return [
        <h3>Item {n}</h3>.
        <p>Description {n}</p>
      ]
    }}
  );
}

同样在React v16.2.0中React Fragments引入了一个称为的新功能,您可以使用它包装多个元素

render() {
  return (
    {[1,2,3].map(function (n, index) {
      return (
        <React.Fragment key={index}>
            <h3>Item {n}</h3>
            <p>Description {n}</p>
        </React.Fragment>
      )
    }}
  );
}

根据文档:

React中的常见模式是组件返回多个元素。片段使您可以将子级列表分组,而无需向DOM添加额外的节点。

用显式语法声明的片段可能具有密钥。一个用例是将一个集合映射到一个片段数组,例如,创建一个描述列表:

function Glossary(props) {
  return (
    <dl>
      {props.items.map(item => (
        // Without the `key`, React will fire a key warning
        <React.Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </React.Fragment>
      ))}
    </dl>
  );
}

键是唯一可以传递给Fragment的属性。将来,我们可能会增加对其他属性(例如事件处理程序)的支持。


7

另外,您可能想在React组件的某些辅助函数中返回几个列表项。只需返回具有以下key属性的html节点数组即可:

import React, { Component } from 'react'

class YourComponent extends Component {
  // ...

  render() {
    return (
      <ul>
        {this.renderListItems()}
      </ul>
    )
  }      

  renderListItems() {
    return [
      <li key={1}><a href="#">Link1</a></li>,
      <li key={2}><a href="#">Link2</a></li>,
      <li key={3} className="active">Active item</li>,
    ]
  }
}

2

您可以createFragment在这里使用。

https://facebook.github.io/react/docs/create-fragment.html

import createFragment from 'react-addons-create-fragment';
...
{[1,2,3].map((n) => createFragment({
    h: <h3>...</h3>,
    p: <p>...</p>
  })
)}

(此处使用ES6和JSX语法)

您首先必须添加react-addons-create-fragment软件包:

npm install --save react-addons-create-fragment

优于Jan Olaf Krems解决方案的优势:反应不会抱怨丢失 key


纠正我,如果我错了,但是您可以简单地手动添加密钥。以jan的示例为例:第一个数组项获取例如<h3 key = {i}> </ h3>,第二个数组项sth稍有不同,如<p> key = {i +'-foo'}> </ p>
书呆子

2

更新

使用React Fragment。这很简单。链接到片段文档。

render() {
  return (
    <>
    {[1,2,3].map((value) => <div>{value}</div>)}
    </>
  );
}

旧答案-已过时

当React> 16时,您可以使用react-composite

import { Composite } from 'react-composite';

// ...

{[1,2,3].map((n) => (
  <Composite>
    <h2>Title {n}</h2>
    <p>Description {n}</p>
  </Composite>
))};

当然,必须安装react-composite。

npm install react-composite --save

0

通过React片段<></>和它很简单React.Fragment

return (
    <>
      {[1, 2, 3].map(
        (n, index): ReactElement => (
          <React.Fragment key={index}>
            <h3>Item {n}</h3>
            <p>Description {n}</p>
          </React.Fragment>
        ),
      )}
    </>
  );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.