2046

我试图在React JSX中执行以下操作(其中ObjectRow是一个单独的组件):

<t车身>for(var i=0;i<numrows;i++){<对象行/>} </tbody>

我意识到并理解为什么这不是有效的JSX,因为JSX映射到函数调用。然而,由于来自模板领域并且是JSX的新手,我不确定如何实现上述目标(多次添加组件)。

10
  • 69
    需要注意的是,在JSX中,JavaScript语法周围需要{}标记。这可能会有帮助facebook.github.io/react/docs/…. 评论 2015年12月24日18:25
  • 46
    让todos=this.props.todos.map((todo)=>{return<h1>{todo.title}</h1>}) 评论 2017年1月15日19:58
  • @OverCoder为什么要将整个返回放在{}标记中,它将是=>return<h1>{todo.title}</h1>不是吗? 评论 2020年3月17日7:41
  • 13
    @pravinpoudel实际上这个答案很古老,更像让todos=this.props.todos.map(t=><h1>{t.title}</h1>):) 评论 2020年3月17日上午10:16
  • “for”不返回值,您需要在示例中为JSX返回数组元素。 评论 2020年10月1日16:15

85个答案85

重置为默认值
1802

把它想象成只是调用JavaScript函数。你不能使用对于函数调用的参数所在的循环:

返回tbody(for(设i=0;i<numrows;i++){对象行()} )

了解其功能表格主体正在传递一个对于循环作为参数&导致语法错误。

但您可以创建一个数组,然后将其作为参数传入:

常量行=[];for(设i=0;i<numrows;i++){rows.push(ObjectRow());}返回tbody(行);

使用JSX时,基本上可以使用相同的结构:

常量行=[];for(设i=0;i<numrows;i++){//注意:我们在这里添加了一个关键属性,以允许react唯一地标识每个属性//元素。请参见:https://reactjs.org/docs/lists-and-keys.htmlrows.push(<ObjectRow键={i}/>);}返回<tbody>{rows}</tbody>;

顺便说一句,我的JavaScript示例几乎就是JSX示例转换的内容。巴别塔REPL了解JSX的工作原理。

1
  • 2
    for循环的详细信息。你只需要数组.from({length:numrows}).map((it,index)=><ObjectRow键={}/>) 评论 2022年9月26日4:10
1176

我不确定这是否适合你的情况,但通常地图是一个很好的答案。

如果这是您的代码对于循环:

<t车身>for(var i=0;i<对象长度;i++){<ObjectRow obj={objects[i]}键={i}>}</tbody>

你可以这样写地图:

<t车身>{对象.map(函数(对象,i){return<ObjectRow obj={object}key={i}/>;})}</tbody>

ES6语法:

<t车身>{objects.map((object,i)=><ObjectRow obj={object}key={i}/>)}</tbody>
4
  • 78
    如果iterate是数组,那么Map更有意义;如果是数字,则for循环是合适的。 评论 2015年4月26日18:40
  • 28
    {objects.map((o,i)=><ObjectRow obj={o}key={i}/>}使用Reactify的ES6支架或Babel。
    – 史蒂夫
    评论 2015年7月27日10:24
  • 如果要返回多行JSX,请在所有行周围使用括号,即。return(…您在此处的行…) 评论 2022年1月7日20:05
  • 如果嵌套组件具有删除事件,则不要将索引用作键。 评论 2022年1月12日5:18
746

如果您还没有数组来映射()就像@FakeRainBrigand的答案,并希望将其内嵌,以便源布局与比@SophieAlpert的答案更接近的输出相对应:

使用ES2015(ES6)语法(排列和箭头函数)

http://plnkr.co/edit/mfqFWODVy8dKQQOkIEGV?p=预览

<t车身>{[…数组(10)].map((x,i)=><ObjectRow键={i}/>)}</tbody>

回复:与巴别塔一起运输警告页面这么说阵列起始位置需要传播,但目前(5.8.23版)当传播一个真实的阵列.我有一个文件问题公开澄清这一点。但使用时请自行承担风险。

香草ES5

阵列应用

<t车身>{Array.apply(0,Array(10)).map(函数(x,i){return<ObjectRow键={i}/>;})}</tbody>

内联IIFE

http://plnkr.co/edit/4kQjdTzd4w69g8Suu2hT?p=预览

<t正文>{(函数(行、i、len){while(++i<=长度){rows.push(<ObjectRow键={i}/>)}返回行;})([], 0, 10)}</tbody>

结合其他答案的技巧

保持源布局与输出相对应,但使内联部分更加紧凑:

渲染:函数(){var行=[],i=0,len=10;while(++i<=len)行。push(i);返回(<t车身>{rows.map(函数(i){return<ObjectRow键={i}索引={i{/>;})}</tbody>);}

使用ES2015语法&阵列方法

使用数组.原型.填充您可以这样做,作为使用上述排列的替代方法:

<t车身>{数组(10).fill(1).map((el,i)=><ObjectRow键={i}/>)}</tbody>

(我认为你实际上可以省略填充(),但我对此并不完全赞同。)感谢@FakeRainBrigand在早期版本的填充()解决方案(参见修订版)。

钥匙

在所有情况下钥匙attr减轻了开发构建的警告,但在子级中不可访问。如果希望子级中的索引可用,可以传递一个额外的属性。请参见列表和键供讨论。

1
  • 2
    请不要创建数组只是从0..N迭代,这是Javascript的峰值。 评论 2021年12月2日16:18
139

简单地使用地图 阵列ES6语法的方法:

<t车身>{items.map(item=><ObjectRow键={item.id}名称={items.name}/>)}</tbody>

别忘了钥匙财产。

0
115

使用阵列映射函数是循环通过阵列并根据中的元素创建组件反应。这是一种很好的循环方式,非常有效,而且是一种简洁的循环方式JSX公司.它是唯一的方法是首选方式。

还有,别忘了有一个唯一密钥根据需要每次迭代。这个map函数从0创建唯一索引,但不建议使用生成的索引,但如果值是唯一的或有唯一键,则可以使用它们:

<t车身>{numrows.map(x=><ObjectRow键={x.id}/>)}</tbody>

此外,还有几行MDN公司如果您不熟悉Array上的map函数:

map为数组,并根据结果构造一个新数组。回调仅对具有赋值的数组的索引调用,包括未定义的。它不调用缺少的元素数组(即从未设置的索引删除或从未赋值)。

回调由三个参数调用:元素的值,元素的索引和正在遍历的Array对象。

如果向映射提供thisArg参数,它将用作回调就是这个值。否则,未定义的值将用作就是这个值。回调最终观察到的这个值是根据通常的规则确定通过函数。

map不会改变调用它的数组(尽管回调(如果调用的话)。

1
  • 阵列#映射不是异步的!
    – 费拉杰
    评论 2017年8月17日1:51
89

如果您已经在使用洛达什,的_.次函数很方便。

从“React”导入React,{Component};导入从“./Select”中选择;从“lodash”导入;导出默认类App extends Component{渲染(){返回(<div className=“container”><ol>{_.倍(3,(i)=>(重复3次</li>))}</ol></div>);}}
2
  • 2
    仅导入来自Lodash,而不是整个图书馆。在开发期间,可以在Lodash发布更新时避免向后不兼容,但在生产中,导入整个库需要花费几秒钟的时间。 评论 2022年1月12日5:20
  • @coder9833idls可能需要切换到洛达什·埃斯为了摇树工作,不是吗? 评论 2022年1月12日18:41
84

有多种方法可以做到这一点。JSX最终会被编译为JavaScript,所以只要您编写有效的JavaScript,您就会做得很好。

我的答案旨在巩固这里介绍的所有精彩方法:

如果没有对象数组,只需输入行数:

返回块,创建阵列和使用数组原型.map:

渲染(){返回(<t车身>{数组(numrows).fill(null).map((value,index)=>(<ObjectRow键={index}>))}</tbody>);}

返回块,只需使用普通JavaScript对于循环:

渲染(){让行=[];for(设i=0;i<numrows;i++){push(<ObjectRow键={i}/>);}返回(<tbody>{rows});}

立即调用的函数表达式:

渲染(){返回(<t车身>{(() => {让行=[];for(设i=0;i<numrows;i++){push(<ObjectRow键={i}/>);}返回行;})()}</tbody>);}

如果你有一个对象数组

返回块,.map()每个对象到<对象行>组件:

渲染(){返回(<t车身>{objectRows.map((行,索引)=>(<ObjectRow键={index}数据={row}/>))}</tbody>);}

返回块,只需使用普通JavaScript对于循环:

渲染(){让行=[];for(设i=0;i<objectRows.length;i++){rows.push(<ObjectRow键={i}数据={objectRows[i]}/>);}返回(<tbody>{rows});}

立即调用的函数表达式:

渲染(){返回(<t正文>{(() => {常量行=[];for(设i=0;i<objectRows.length;i++){push(<ObjectRow键={i}数据={objectRows[i]}/>);}返回行;})()}</tbody>);}
0
57

您还可以在返回块外提取:

渲染:函数(){var行=[];for(var i=0;i<numrows;i++){push(<ObjectRow键={i}/>);} 返回(<tbody>{rows}</tbody>);}
0
48

你可能想结帐反应模板,它允许您在React中使用JSX样式的模板,并带有一些指令(例如rt-重复).

您的示例,如果您使用反应模板,将是:

<t车身><ObjectRow rt-repeat=“objects中的obj”/></tbody>
0
47

如果你选择在里面转换这个返回()提供方法,最简单的选项是使用地图()方法。使用Map()函数将数组映射到JSX语法,如下所示(使用ES6语法).


父组件内部:

<t车身>{objectArray.map(object=><ObjectRow键={object.id}对象={obbject.value}/>)}</tbody>

请注意钥匙属性添加到子组件中。如果您没有提供键属性,您可以在控制台上看到以下警告。

警告:数组或迭代器中的每个子级都应该有独特的“钥匙”道具。

注:人们常犯的一个错误是使用指数作为迭代时的密钥。使用指数作为键的元素是一个反模式,您可以阅读有关它的更多信息在这里简而言之,如果静态列表,从不使用指数作为关键。


现在在对象行组件,您可以从其属性访问对象。

ObjectRow组件内部

const{object}=this.props

或者

const对象=this.props.object

这将获取从父组件传递到变量的对象对象在中对象行组件。现在,您可以根据自己的目的输出该对象中的值。


参考文献:

JavaScript中的map()方法

ECMAScript 6或ES6

1
  • 这对我来说很有效,但我添加了“/”来结束“<ObjectRow/>”标记。
    – 亚当
    评论 2022年2月7日18:18
39

如果数量是一个数组,非常简单:

<t正文>{numrows.map(item=><ObjectRow/>)}</tbody>

React中的数组数据类型要好得多。一个数组可以支持一个新的数组,并支持filter、reduce等。

0
35

这可以通过多种方式实现。

  1. 如上所述,在返回将所有元素存储在数组中

  2. 内部循环返回

    方法1:

    让容器=[];设arr=[1,2,3]//可以是任何数组、对象arr.forEach((val,索引)=>{容器.推送(<div键={index}>val值</div>)/*** 1. 所有循环生成的元素都需要密钥* 2. 数组中只能放置一个父元素*例如,容器.推送(*<div键={index}>val值</div><div>这将引发错误</div>)**/});返回(<div><div>这里有任何东西<div>{container}</div></div>)

    方法2:

    返回(<div><div>这里有任何东西<div>{(() => {让容器=[];设arr=[1,2,3]//可以是任何数组、对象arr.forEach((val,索引)=>{容器推送(<div键={index}>val值</div>)});返回容器;})()}</div></div>)
1
  • 是 啊。在我当前的项目中,我使用方法1,即使用Array.prototype和forEach()方法创建HTML选择元素,该元素由数据库中的数据填充。然而,我更可能用Array.prototype.map()方法替换它们,因为map方法看起来更紧凑(代码更少)。
    – Lex软件
    评论 2019年3月15日15:08
33

有几个答案指向使用地图声明。下面是在功能列表要列出的组件功能基于JSON数据结构的组件特征.

const FeatureList=({features,onClickFeature,onClikLikes})=>(<div className=“feature-list”>{features.map(feature=><功能key={feature.id}{…功能}onClickFeature={()=>onClickFeature(feature.id)}onClickLikes={()=>onClickLikes(feature.id)}/>)}</div>);

您可以查看完整的FeatureList代码在GitHub上。这个此处列出了特征夹具.

1
  • 在处理JSON数据时,例如在使用fetch API从数据库检索数据时,我依赖于使用Array.prototype.map方法。这是一种方便且行之有效的方法。
    – Lex软件
    评论 2019年3月15日14:32
32

要循环多次并返回,可以通过以下方法实现地图:

<t车身>{Array.from(数组(i)).map(()=><对象行/>)}</tbody>

哪里i=次数


如果要为渲染组件指定唯一的键ID,可以使用反应。子级.to数组按照React文档

反应。子级.to数组

以平面数组的形式返回子级不透明数据结构,并将键分配给每个子级。如果要操作呈现方法中的子集合,特别是要在传递this.props.children之前对其重新排序或切片,则此功能非常有用。

注:

反应。子项.toArray()在展平子级列表时,更改键以保留嵌套数组的语义。也就是说,toArray在返回的数组中为每个键添加前缀,以便每个元素的键的作用域都是包含它的输入数组。

<t正文>{反应。子级.to数组(Array.from(数组(i)).map(()=><对象行/>))}</tbody>
32

假设您所在州有一系列项目:

[{name:“item1”,id:1},{name:”item2“,id:2},}name:”tem3“,id:3}]<t车身>{this.state.items.map((item)=>{<ObjectRow键={item.id}名称={itet.name}/>})}</tbody>
  • 我想你可能需要去掉地图(项目)后面的{},这似乎对我很有用。
    – 伊恩
    评论 2016年12月10日17:22
  • 只是一个想法:{this.state.items?.map((item)=>,或我最喜欢的语法:{this.state.items&&this.state.items.map((item)=>并从中删除不必要的()(项目)因为只有一个参数。异步呈现组件并且还没有导入本地状态会让您感到沮丧。 评论 2022年1月12日5:23
  • 在这种情况下,它不会呈现任何内容。您需要添加返回关键字在您的{}或需要删除{}.{this.state.items.map((item)=>{return(<ObjectRow键={item.id}名称={items.name}/>)})}{this.state.items.map((item)=>(<ObjectRow键={item.id}名称={items.name}/>)} 评论 2023年5月19日8:05
29

2015年ECMAScript/巴别塔可能是使用生成器函数创建JSX数组:

函数*jsxLoop(次数,回调){for(var i=0;i<次数;++i)收益回调(i);}...<t车身>{[…jsxLoop(数行,i=><ObjectRow键={i}/>)]}</tbody>
24

2015年欧洲标准阵列起始位置使用地图功能+键

如果你没有什么.map()你可以使用数组.from()使用地图重复元素的功能:

<t车身>{Array.from({length:5},(value,key)=><ObjectRow key={key}/>)}</tbody>
21

…或者您也可以准备一个对象数组并将其映射到函数以获得所需的输出。我更喜欢这样,因为它有助于我保持良好的编码实践,在渲染的返回中没有逻辑。

渲染(){常量映射项=[];for(设i=0;i<项长度;i++)mapItem.prush(i);const singleItem=>(项,索引){//item数组中的单个项//数组中项目的索引//可以在这里实现任何逻辑返回(<对象行/>)}返回({mapItem.map(singleItem)})}
21

我使用这个:

gridItems=this.state.applications.map(app=><ApplicationItem key={app.Id}app={app}/>);

附言:千万不要忘记钥匙,否则你会收到很多警告!

1
  • 或者,如果您的项没有.Id号财产,比如map((item,index)=><Foo键={index}>{item}</Foo>
    – 孔图尔
    评论 2017年3月30日9:26
19

这里有一个简单的解决方案。

var Object_rows=[];for(var i=0;i<numrows;i++){Object_rows.push(<ObjectRow/>);}<tbody>{Object_rows}</tbody>;

不需要映射和复杂代码。您只需要将行推送到数组并返回值即可呈现它。

1
  • 1
    在创建html select元素时,我首先想到了这种类似的技术,所以我使用了它,尽管我使用了forEach()方法。但是当我重读关于Lists和Keys主题的React文档时,我发现他们使用了map()方法,这里的几个答案也显示了这一点。这让我觉得这是最好的方式。我同意,因为它看起来更紧凑(代码更少)。
    – Lex软件
    评论 2019年3月15日15:20
18

只需使用.map()循环浏览您的收藏并返回<对象行>每个迭代中带有道具的项目。

假设物体是某个数组。。。

<t车身>{objects.map((obj,index)=><ObjectRow obj={obj}key={index}/>)}</tbody>
18

当然,你可以用另一个答案建议的.map来求解。如果您已经使用巴别塔,您可以考虑使用jsx控制语句.

它们需要一些设置,但我认为就可读性而言是值得的(尤其是对于非React开发人员)。如果你用短绒,还有eslint-plugin-jsx控制语句.

17

您的JSX代码将编译为纯JavaScript代码,任何标记都将替换为反应元件物体。在JavaScript中,不能多次调用一个函数来收集其返回的变量。

这是非法的,唯一的方法是使用数组存储函数返回的变量。

或者您可以使用数组原型.map哪个可用自JavaScript ES5以来来处理这种情况。

也许我们可以编写其他编译器来重新创建一个新的JSX语法来实现重复函数,就像角度ng-重复.

16

我倾向于选择一种编程逻辑发生在返回值之外的方法提供这有助于保持实际呈现的内容易于摸索。

所以我可能会这样做:

从“lodash”导入;...const TableBody=({对象})=>{const objectRows=对象.map(obj=><对象行对象={obj}/>);return<tbody>{objectRows}</tbody>;}

诚然,这是一个如此少的代码量,内联它可能会很好地工作。

0
15

这是React文档中的一个示例,JavaScript表达式作为子级:

功能项(道具){return<li>{props.message}</li>;}函数TodoList(){const todos=['完成文档','提交pr','等待审核'];返回(<ul>{todos.map((message)=><项键={message}消息={mesage}/>)}</ul>);}

至于你的情况,我建议你这样写:

函数render(){返回(<t车身>{numrows.map((roe,index)=><ObjectRow键={index}/>)}</tbody>);}

请注意钥匙非常重要,因为React使用钥匙以区别数组中的数据。

1
  • 有可能在一个数字上绘制地图吗?我在控制台上试过了,但没用。 评论 2022年3月12日17:29
15

您可以在React中使用.map()对于循环。

<t车身>{newArray.map(()=><ObjectRow/>)}</tbody>
13

因为您在JSX代码中编写JavaScript语法,所以需要将JavaScript代码用花括号括起来。

行=()=>{var行=[];for(设i=0;i<numrows;i++){rows.push(<ObjectRow/>);}返回行;}<t车身>{this.row()}</tbody>
0
12

随着时间的推移,语言变得越来越成熟,我们经常会遇到这样的常见问题。问题是将组件循环“n”次。

{[…new Array(n)].map((item,index)=><MyComponent key={index}/>)}

其中,n-是要循环的次数。项目将是未定义的,并且指数一切如常。也,ESLint公司不鼓励使用数组索引作为键。

但您的优点是不需要在之前初始化数组,最重要的是避免了对于循环。。。

为了避免未定义项带来的不便,可以使用_,以便在进行线头提取时忽略它,不会抛出任何线头提取错误,例如

{[…new Array(n)].map((_,index)=><MyComponent键={index}/>)}
12

如果你真的想要对于循环等价(只有一个数字,而不是数组),只需使用范围来自Lodash.

不要重新发明轮子,也不要混淆代码。只需使用标准实用程序库。

从“lodash/range”导入范围范围(4);// => [0, 1, 2, 3]范围(1,5);// => [1, 2, 3, 4]
11

您还可以使用自我调查功能:

返回<tbody>{(() => {let行=[]for(var i=0;i<numrows;i++){push(<ObjectRow键={i}/>)}返回行})()}</tbody>
  • 1
    在render中使用匿名函数被认为不是一种好的反应方式,因为在每次重新渲染时都需要重新创建或丢弃这些函数。 评论 2017年9月29日7:25
  • @VlatkoVlahek你把它误认为是在每个渲染周期重新创建函数props能够导致大规模绩效下降。在其他地方创建匿名函数不会对性能产生任何重大影响。 评论 2020年2月20日16:54
  • 1
    @Emile Bergeron这是不久前的事了哈哈。我确实同意,如果这不是一个道具,没有区别。 评论 2020年2月20日18:36

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.