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

Posted

技术标签:

【中文标题】如何在 React 的另一个 return 语句中返回多行 JSX?【英文标题】:How can I return multiple lines JSX in another return statement in React? 【发布时间】:2014-07-13 12:11:33 【问题描述】:

单行可以正常工作:

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

【问题讨论】:

有关此特定问题的更多信息:github.com/facebook/react/issues/2127 不是return ("asdf" "asdf"); 你想要return ["asdf", "asdf"]; 【参考方案1】:

尝试将标签视为函数调用(参见the documentation)。那么第一个就变成了:

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

第二个:

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

现在应该清楚第二个 sn-p 没有真正意义(在 javascript 中不能返回多个值)。您必须将其包装在另一个元素中(很可能是您想要的,这样您还可以提供有效的 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 很可能会更好。

【讨论】:

是的,实际上已经清楚地记录了facebook.github.io/react/tips/… 使用没有 flatten 位的 return ([...]) 可以让我得到完全符合我要求的标记,尽管返回的数组不能被展平,但在我的特定情况下它不会影响最终输出。还是这样? 谢谢!直到!更新我的答案以包含指向显示 flatten 是可选的 JSFiddle 的链接。还将包含 React 文档的链接。 这不再有效(截至 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. @TimFletcher 可以返回一个数组作为渲染组件的一部分,例如&lt;div&gt; this.props.foos.map(function() return &lt;Foo /&gt; ) &lt;/div&gt;。但是组件的 render 函数不能在不包装的情况下返回该数组,例如在一个 div 中。【参考方案2】:

似乎 Jan Olaf Krems's answer 关于返回一个数组不再适用(可能从 React ~0.9 开始,正如 @dogmatic69 在 a comment 中所写)。

The documentation 表示需要返回单个节点:

JSX 根节点的最大数量

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

别忘了 JSX 会编译成普通的 JS;返回两个 函数并没有真正的语法意义。同样,不要放 三元组中不止一个孩子。

在许多情况下,您可以简单地将内容包装在 &lt;div&gt;&lt;span&gt; 中。

就我而言,我想返回多个&lt;tr&gt;s。我将它们包裹在 &lt;tbody&gt; 中——一个表格可以有多个主体。

从 React 16.0 开始,显然再次允许返回一个数组,只要每个元素都有一个 keyNew render return types: fragments and strings

React 16.2 允许您使用 &lt;Fragment&gt;…&lt;/Fragment&gt; 甚至 &lt;&gt;…&lt;/&gt; 包围元素列表,如果您更喜欢使用数组:https://reactjs.org/docs/fragments.html

【讨论】:

如果要返回多个&lt;li&gt;怎么办?假设我不能把它全部包装在&lt;ul&gt; @Banjocat 恐怕我不知道:/ 你可以嵌套列表,所以你可以返回类似&lt;li&gt;&lt;ul&gt;&lt;li&gt;one&lt;/li&gt;&lt;li&gt;two&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;的东西,如果这适用于你的情况.或者:包装 div 不会严格有效,但也许它在所有相关浏览器中都可以正常呈现?如果您尝试过,请告诉我们。 @Banjocat...我很想知道您的问题的更好答案。也许你应该把它当作一个常规的 *** 问题,看看你是否得到不同的答案。 @user1175849 也许可以发布那个问题:) @HenrikN Fwiw,将li 的“子集”包装在spandiv 对我来说效果不佳。 div 严重破坏了渲染,而且,至少在我的用例中,span 弄乱了 CSS。 2¢: 尝试返回 lis 的几个子集是代码异味。我们使用ul 作为一种下拉菜单,我最初希望许多组件返回lis 的“部分”。最后,最好将所有菜单代码放入“锚定”在ul 的单个组件中,而不是从多个来源中硬塞到lis 中。我认为它还让 UI 的心智模型更加简洁。【参考方案3】:

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

key 是唯一可以传递给 Fragment 的属性。在里面 将来,我们可能会添加对其他属性的支持,例如事件 处理程序。

【讨论】:

【参考方案4】:

此外,您可能希望在 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>,
    ]
  

【讨论】:

【参考方案5】:

更新

使用反应片段。这很简单。 Link 分片文档。

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

【讨论】:

【参考方案6】:

您可以在此处使用createFragment。请参阅Keyed Fragments

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's solution 的优势:React 不会抱怨缺少 key

【讨论】:

如果我错了,请纠正我,但您可以手动添加密钥。使用 jan 的示例:第一个数组项获取例如

和第二个数组项略有不同,例如

key=i + '-foo'>

【参考方案7】:

通过 React 片段 &lt;&gt;&lt;/&gt;React.Fragment 很简单:

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

【讨论】:

【参考方案8】:

当您不在当前项目中时会发生这种情况,我在一个文件夹中有三个项目并出现此错误。

一旦切换到项目,问题就消失了。

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于如何在 React 的另一个 return 语句中返回多行 JSX?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 组件中使用 switch 语句?

在 React 渲染方法中使用 for 在 return 语句中失败

如何在 React.js 的另一个组件中更新组件状态变量的值?

如何从 React 的另一个组件中读取变量?

从反应中的另一个组件更新组件

如何将一个道具作为变量传递给 React 中的另一个道具?