React JSX中的循环

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

<tbody>for (var i=0; i < numrows; i++) {<ObjectRow/>}</tbody>

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

1626387 次浏览

把它想象成你只是在调用JavaScript函数。您不能使用for循环来调用函数的参数:

return tbody(for (let i = 0; i < numrows; i++) {ObjectRow()})

查看函数tbody如何作为参数传递for循环-导致语法错误。

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

const rows = [];for (let i = 0; i < numrows; i++) {rows.push(ObjectRow());}return tbody(rows);

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

const rows = [];for (let i = 0; i < numrows; i++) {// note: we are adding a key prop here to allow react to uniquely identify each// element in this array. see: https://reactjs.org/docs/lists-and-keys.htmlrows.push(<ObjectRow key={i} />);}return <tbody>{rows}</tbody>;

顺便说一句,我的JavaScript示例几乎正是JSX示例转换成的内容。使用BabelREPL来感受JSX的工作原理。

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

如果这是你的进行循环代码:

<tbody>for (var i=0; i < objects.length; i++) {<ObjectRow obj={objects[i]} key={i}>}</tbody>

你可以这样写地图

<tbody>{objects.map(function(object, i){return <ObjectRow obj={object} key={i} />;})}</tbody>

ES6语法:

<tbody>{objects.map((object, i) => <ObjectRow obj={object} key={i} />)}</tbody>

您可能希望签出反应模板,它确实允许您在React中使用JSX风格的模板,并带有一些指令(例如rt-重复)。

你的例子,如果你使用react-tem的,将是:

<tbody><ObjectRow rt-repeat="obj in objects"/></tbody>

如果您还没有像@FakeRainBrigand的答案那样的map()数组,并且想要内联此数组,以便源布局对应于比@SophieAlpert的答案更接近的输出:

使用ES2015(ES6)语法(扩展和箭头函数)

http://plnkr.co/edit/mfqFWODVy8dKQQOkIEGV?p=preview

<tbody>{[...Array(10)].map((x, i) =><ObjectRow key={i} />)}</tbody>

回复:用巴别塔转译,它的注意事项页Array.from是传播所必需的,但目前(v5.8.23)在传播实际的Array时似乎并非如此。我有一个留档问题打开来澄清这一点。但使用你自己的风险或聚填料。

香草ES5

Array.apply

<tbody>{Array.apply(0, Array(10)).map(function (x, i) {return <ObjectRow key={i} />;})}</tbody>

内联生活

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

<tbody>{(function (rows, i, len) {while (++i <= len) {rows.push(<ObjectRow key={i} />)}return rows;})([], 0, 10)}</tbody>

结合其他答案的技巧

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

render: function () {var rows = [], i = 0, len = 10;while (++i <= len) rows.push(i);
return (<tbody>{rows.map(function (i) {return <ObjectRow key={i} index={i} />;})}</tbody>);}

使用ES2015语法和Array方法

使用Array.prototype.fill,您可以将其作为使用传播的替代方法,如上所示:

<tbody>{Array(10).fill(1).map((el, i) =><ObjectRow key={i} />)}</tbody>

(我认为你实际上可以省略对fill()的任何参数,但我不是100%)感谢@FakeRainBrigand纠正了我在早期版本的fill()解决方案中的错误(参见修订)。

key

在所有情况下,key attr都会减轻开发版本的警告,但在子级中无法访问。如果您希望索引在子级中可用,您可以传递额外的attr。请参阅列表和键进行讨论。

您的JSX代码将编译成纯JavaScript代码,任何标签都将被ReactElement对象替换。在JavaScript中,您不能多次调用函数来收集它们返回的变量。

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

或者您可以使用#0(可用由于JavaScript ES5)来处理这种情况。

也许我们可以编写其他编译器来重新创建一个新的JSX语法来实现一个重复函数,就像Angular的#0一样。

如果您已经在使用lodash,则#1函数很方便。

import React, { Component } from "react";import Select from "./Select";import _ from "lodash";
export default class App extends Component {render() {return (<div className="container"><ol>{_.times(3, (i) => (<li key={i}>repeated 3 times</li>))}</ol></div>);}}

你也可以在返回块之外提取:

render: function() {var rows = [];for (var i = 0; i < numrows; i++) {rows.push(<ObjectRow key={i}/>);}
return (<tbody>{rows}</tbody>);}

我倾向于支持编程逻辑发生在render返回值之外的方法。这有助于保持实际呈现的内容易于理解。

所以我可能会这样做:

import _ from 'lodash';
...
const TableBody = ({ objects }) => {const objectRows = objects.map(obj => <ObjectRow object={obj} />);
return <tbody>{objectRows}</tbody>;}

不可否认,这是如此少量的代码,内联它可能会工作得很好。

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

render() {const mapItem = [];for(let i =0;i<item.length;i++)mapItem.push(i);const singleItem => (item, index) {// item the single item in the array// the index of the item in the array// can implement any logic herereturn (<ObjectRow/>)
}return(<tbody>{mapItem.map(singleItem)}</tbody>)}

有几个答案指向使用map语句。这是一个完整的示例,使用产品列表组件中的迭代器根据名为功能的JSON数据结构列出功能组件。

const FeatureList = ({ features, onClickFeature, onClickLikes }) => (<div className="feature-list">{features.map(feature =><Featurekey={feature.id}{...feature}onClickFeature={() => onClickFeature(feature.id)}onClickLikes={() => onClickLikes(feature.id)}/>)}</div>);

您可以在GitHub上查看完整的特征列表代码功能夹具在这里列出

这可以通过多种方式完成。

  1. 如上所述,在return之前将所有元素存储在数组中

  2. 内部循环return

    方法1令容器=[];let arr=[1,2,3]//可以是任何数组,对象

    arr.forEach((val, index) => {container.push(<div key={index}>val</div>)/*** 1. All loop generated elements require a key* 2. only one parent element can be placed in Array* e.g. container.push(*         <div key={index}>val</div><div>this will throw error</div>)**/});return (<div><div>any things goes here</div><div>{container}</div></div>)

    方法2

    return (<div><div>any things goes here</div><div>{(() => {let container = [];let arr = [1, 2, 3] //can be anything array, objectarr.forEach((val, index) => {container.push(<div key={index}>val</div>)});return container;})()}</div></div>)

假设我们在您的状态中有一组项目:

[{name: "item1", id: 1}, {name: "item2", id: 2}, {name: "item3", id: 3}]
<tbody>{this.state.items.map((item) => {<ObjectRow key={item.id} name={item.name} />})}</tbody>

当然,您可以按照另一个答案的建议使用. map进行求解。如果您已经使用了巴别塔,您可以考虑使用js x-control-语句

它们需要一些设置,但我认为它在易读性方面是值得的(尤其是对于非React开发人员)。如果你使用linter,也有es lint-plugin-js x-control-语句

简单地使用地图数组方法和ES6语法:

<tbody>{items.map(item => <ObjectRow key={item.id} name={item.name} />)}</tbody>

不要忘记key属性。

如果您选择在呈现方法的返回值中转换它,最简单的选择是使用地图方法。使用map()函数将您的数组映射到JSX语法,如下所示(使用ES6语法)。


父组件内部

<tbody>{ objectArray.map(object => <ObjectRow key={object.id} object={object.value} />) }</tbody>

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

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

备注:人们常犯的一个错误是在迭代时使用index作为键。使用元素的index作为键是一种反模式,你可以阅读更多关于它的信息这里。简而言之,如果它是没有一个静态列表,永远不要使用index作为键。


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

在ObjectRow组件内部

const { object } = this.props

const object = this.props.object

这应该会获取您从父组件传递给对象行组件中变量object的对象。现在您可以根据您的目的吐出该对象中的值。


参考文献:

JavaScript中的map()方法

ECMAScript 6 or ES6

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

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

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

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

function* jsxLoop(times, callback){for(var i = 0; i < times; ++i)yield callback(i);}
...
<tbody>{[...jsxLoop(numrows, i =><ObjectRow key={i}/>)]}</tbody>

如果麻瓜是一个数组,它很简单:

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

React中的数组数据类型要好得多。一个数组可以返回一个新数组,支持过滤、减少等。

由于您是在JSX代码中编写JavaScript语法,因此需要将JavaScript代码包装在花括号中。

row = () => {var rows = [];for (let i = 0; i<numrows; i++) {rows.push(<ObjectRow/>);}return rows;}<tbody>{this.row()}</tbody>

我用这个:

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

PS:永远不要忘记钥匙,否则你会有很多警告!

我用它就像

<tbody>{ numrows ? (numrows.map(obj => { return <ObjectRow /> })) : null}</tbody>

你可以这样做:

let foo = [1,undefined,3]{ foo.map(e => !!e ? <Object /> : null )}

使用数组映射函数是循环遍历数组元素并在React中根据它们创建组件的一种非常常见的方法。这是一种很好的循环方式,它非常有效,并且是在JSX中进行循环的整洁方式。这是没有的唯一方法,但首选方式。

此外,不要忘记根据需要为每次迭代设置唯一密钥map函数从0创建一个唯一索引,但不建议使用生成的索引,但如果你的值是唯一的或者有一个唯一的键,你可以使用它们:

<tbody>{numrows.map(x=> <ObjectRow key={x.id} />)}</tbody>

此外,如果您不熟悉Array上的map函数,请参阅MDN中的几行:

map为每个元素调用一次提供的回调函数数组,按顺序排列,并从结果构造一个新数组。回调仅对具有赋值的数组的索引调用,不需要为缺少的元素调用数组(即从未设置过的索引,这些索引已被删除或从未分配过值)。

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

如果将thisArg参数提供给map,它将被用作回调是这个值。否则,未定义的值将被用作它的this值。回调最终可观察到的值是根据通常的规则来确定这个看到的通过一个函数。

map不会改变调用它的数组(尽管回调,如果调用,可以这样做)。

只需使用.map()循环遍历您的集合并返回<ObjectRow>项,其中包含每次迭代的道具。

假设objects是某个数组…

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

以下是React留档作为子代的JavaScript表达式的示例:

function Item(props) {return <li>{props.message}</li>;}
function TodoList() {const todos = ['finish doc', 'submit pr', 'nag dan to review'];return (<ul>{todos.map((message) => <Item key={message} message={message} />)}</ul>);}

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

function render() {return (<tbody>{numrows.map((roe, index) => <ObjectRow key={index} />)}</tbody>);}

请注意关键非常重要,因为React使用关键来区分数组中的数据。

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

我的回答旨在巩固这里已经提出的所有奇妙方法:

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

return块中,创建Array并使用Array.prototype.map

render() {return (<tbody>{Array(numrows).fill(null).map((value, index) => (<ObjectRow key={index}>))}</tbody>);}

return块之外,只需使用普通的JavaScript进行循环:

render() {let rows = [];for (let i = 0; i < numrows; i++) {rows.push(<ObjectRow key={i}/>);}return (<tbody>{rows}</tbody>);}

立即调用函数表达式:

render() {return (<tbody>{(() => {let rows = [];for (let i = 0; i < numrows; i++) {rows.push(<ObjectRow key={i}/>);}return rows;})()}</tbody>);}

如果你有一个对象数组

return块中,.map()每个对象到<ObjectRow>组件:

render() {return (<tbody>{objectRows.map((row, index) => (<ObjectRow key={index} data={row} />))}</tbody>);}

return块之外,只需使用普通的JavaScript进行循环:

render() {let rows = [];for (let i = 0; i < objectRows.length; i++) {rows.push(<ObjectRow key={i} data={objectRows[i]} />);}return (<tbody>{rows}</tbody>);}

立即调用函数表达式:

render() {return (<tbody>{(() => {const rows = [];for (let i = 0; i < objectRows.length; i++) {rows.push(<ObjectRow key={i} data={objectRows[i]} />);}return rows;})()}</tbody>);}

React元素是简单的JavaScript,因此您可以遵循JavaScript的规则。您可以在JavaScript中使用for循环,如下所示:-

<tbody>for (var i=0; i < numrows; i++) {<ObjectRow/>}</tbody>

但有效和最好的方法是使用.map函数。如下所示:-

<tbody>{listObject.map(function(listObject, i){return <ObjectRow key={i} />;})}</tbody>

在这里,有一件事是必要的:定义密钥。否则它会抛出这样的警告:-

Warning.js:36警告:数组或迭代器中的每个子级都应该有一个独特的“键”道具。检查ComponentName的渲染方法。参见“链接”获取更多信息。

return (<table><tbody>{numrows.map((item, index) => {<ObjectRow data={item} key={index}>})}</tbody></table>);

如果numrow是一个数组,与其他答案一样,最好的方法是map方法。如果不是,并且您只能从JSX访问它,您也可以使用这个ES6方法:

<tbody>{[...Array(numrows).fill(0)].map((value,index)=><ObjectRow key={index} />)}</tbody>

当我想添加一定数量的组件时,我使用一个辅助函数。

定义一个返回JSX的函数:

const myExample = () => {let myArray = []for(let i = 0; i<5;i++) {myArray.push(<MyComponent/>)}return myArray}
//... in JSX
<tbody>{myExample()}</tbody>

您需要向数组中添加元素并呈现元素数组。
这可以帮助减少重新渲染组件所需的时间。

这里有一些粗略的代码可能会有所帮助:

MyClass extends Component {constructor() {super(props)this.state = { elements: [] }}render() {return (<tbody>{this.state.elements}<tbody>)}add() {/** The line below is a cheap way of adding to an array in the state.* 1) Add <tr> to this.state.elements* 2) Trigger a lifecycle update.*/this.setState({elements: this.state.elements.concat([<tr key={elements.length}><td>Element</td></tr>])})}}

如果您真的想在JSX中使用进行循环,您可以使用IIFE

<tbody>{(function () {const view = [];for (let i = 0; i < numrows; i++) {view.push(<ObjectRow key={i}/>);}return view;}())}</tbody>

您还可以使用自调用函数:

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

带有map函数+键的ES2015Array.from

如果你没有.map(),你可以使用Array.from()map函数来重复元素:

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

如果我理解正确,您可以使用此代码:

<tbody>{ new Array(numrows).fill(<ObjectRow/>) }</tbody>

您可以使用此代码:

<tbody>{ new Array(numrows).fill('').map((item, ind) => <ObjectRow key={ind}/>) }</tbody>

还有这个:

<tbody>new Array(numrows).fill(ObjectRow).map((Item, ind) => <Item key={ind}/>)</tbody>

在React中使用地图是迭代数组的最佳实践。

为了防止ES6出现一些错误,在React中这样使用语法映射:

<tbody>{items.map((item, index) => <ObjectRow key={index} name={item.name} />)}</tbody>

在这里,您调用一个组件,因此您不需要在箭头后加上括号。

但你也可以这样做:

{items.map((item, index) => (<ObjectRow key={index} name={item.name} />))}

或:

{items.map((item, index) => {// Here you can log 'item'return (<ObjectRow key={index} name={item.name} />)})}

我这么说是因为如果你在箭头后面放一个括号“{}”,React不会抛出错误并会显示白名单。

好吧,给你。

{[1, 2, 3, 4, 5, 6].map((value, index) => {return <div key={index}>{value}</div>})}

你所要做的就是映射你的数组并返回你想要渲染的任何东西。请不要忘记在返回的元素中使用key

JSX中的循环非常简单。试试这个:

return this.state.data.map((item, index) => (<ComponentName key={index} data={item} />));

用JSX编写:

<tbody>{objects.map((object, i) => (<ObjectRow obj={object} key={i} />));}</tbody>

问题是你没有返回任何JSX元素。对于这种情况还有另一种解决方案,但我会提供最简单的一个:“使用地图函数”!

<tbody>{ numrows.map(item => <ObjectRow key={item.uniqueField} />) }</tbody>

它是如此简单和美丽,不是吗?

如果您需要JSX中的JavaScript代码,请添加{ },然后在这些括号内编写JavaScript代码。就这么简单

以同样的方式,您可以在JSX/React中循环。

说:

<tbody>{`your piece of code in JavaScript` }</tbody>

示例:

<tbody>{ items.map((item, index) => {console.log(item)}) ; // Print itemreturn <span>{index}</span>;} // Looping using map()</tbody>

要循环多次并返回,您可以在#0#1的帮助下实现它:

<tbody>{Array.from(Array(i)).map(() => <ObjectRow />)}</tbody>

其中i = number of times


如果您想为呈现的组件分配唯一的键ID,您可以使用React留档中建议的React.Children.toArray

React.Children.to阵列

将子级不透明数据结构作为一个平面数组返回,并为每个子级分配键。如果您想在渲染方法中操作子级集合,特别是如果您想在传递之前重新排序或切片this.props.children,则非常有用。

备注:

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

<tbody>{React.Children.toArray(Array.from(Array(i)).map(() => <ObjectRow />))}</tbody>

我找到了一个解决方案,按照地图渲染:

 <tbody>{this.getcontent()}</tbody>

单独函数:

getcontent() {const bodyarea = this.state.movies.map(movies => (<tr key={movies._id}><td>{movies.title}</td><td>{movies.genre.name}</td><td>{movies.numberInStock}</td><td>{movies.publishDate}</td><td><buttononClick={this.deletMovie.bind(this, movies._id)}className="btn btn-danger">Delete</button></td></tr>));return bodyarea;}

这个例子很容易解决许多问题。

以下是您可以在React中根据迭代对象数组或普通数组执行的可能解决方案

const rows = [];const numrows = [{"id" : 01, "name" : "abc"}];numrows.map((data, i) => {rows.push(<ObjectRow key={data.id} name={data.name}/>);});
<tbody>{ rows }</tbody>

const rows = [];const numrows = [1,2,3,4,5];for(let i=1, i <= numrows.length; i++){rows.push(<ObjectRow key={numrows[i]} />);};
<tbody>{ rows }</tbody>

最近几天我熟悉的迭代对象数组的更好方法是.map直接在渲染中返回或不返回:

. map返回结果

 const numrows = [{"id" : 01, "name" : "abc"}];<tbody>{numrows.map(data=> {return <ObjectRow key={data.id} name={data.name}/>})}</tbody>

. map不返回

 const numrows = [{"id" : 01, "name" : "abc"}];<tbody>{numrows.map(data=> (<ObjectRow key={data.id} name={data.name}/>))}</tbody>

甚至这段代码也做同样的工作。

<tbody>{array.map(i =><ObjectRow key={i.id} name={i.name} />)}</tbody>

如果您没有键值par,则要打印数组值,请使用以下代码-

<div>{my_arr.map(item => <div>{item} </div> )}</div>

在JSX块中的JavaScript代码周围使用{},以使其正确执行您尝试执行的任何JavaScript操作。

<tr><td>{data.map((item, index) => \{\{item}})}</td></tr>

这有点模糊,但你可以为任何数组交换数据。这将为你提供一个表行和每个项目的表项。如果数组的每个节点中只有一个以上的东西,你将希望通过这样做来专门针对它:

<td>{item.someProperty}</td>

在这种情况下,您将希望用不同的td包围它,并以不同的方式排列前面的示例。

关于迭代数组和生成JSX元素的解决方案有很多。所有这些都很好,但它们都直接在循环中使用索引。建议我们使用数据中的唯一ID作为键,但是当我们没有数组中每个对象的唯一ID时,我们将使用索引作为键,但不建议你直接使用索引作为键。

还有一件事,为什么我们选择. map,但为什么不选择. fo每个,因为. map返回一个新数组。这些天有不同的方法来做. map

下面使用. map的不同版本详细说明了如何使用唯一键以及如何使用. map循环JSX元素。

. map在返回单个JSX元素和唯一id作为键版本时没有返回:

const {objects} = this.state;
<tbody>{objects.map(object => <ObjectRow obj={object} key={object.id} />)}</tbody>

. map在返回多个JSX元素和唯一id作为密钥版本时没有返回

const {objects} = this.state;
<tbody>{objects.map(object => (<div key={object.id}><ObjectRow obj={object} /></div>))}</tbody>

. map在返回单个JSX元素和索引作为键版本时没有返回:

const {objects} = this.state;
<tbody>{objects.map((object, index) => <ObjectRow obj={object} key={`Key${index}`} />)}</tbody>

. map在返回多个JSX元素和索引作为键版本时没有返回:

const {objects} = this.state;
<tbody>{objects.map((object, index) => (<div key={`Key${index}`}><ObjectRow obj={object} /></div>))}</tbody>

. map,返回多个JSX元素和索引作为键版本时返回:

const {objects} = this.state;
<tbody>{objects.map((object, index) => {return (<div key={`Key${index}`}><ObjectRow obj={object} /></div>)})}</tbody>

. map,当返回多个JSX元素和唯一id作为密钥版本时返回:

const {objects} = this.state;
<tbody>{objects.map(object => {return (<div key={object.id}><ObjectRow obj={object} /></div>)})}</tbody>

另一种方法是

render() {const {objects} = this.state;const objectItems = objects.map(object => {return (<div key={object.id}><ObjectRow obj={object} /></div>)})return(<div><tbody>{objectItems}</tbody></div>)}

如果您想使用存储为Integer值的特定行数,则提供更直接的解决方案。

typedArrays的帮助下,我们可以通过以下方式实现所需的解决方案。

// Let's create a typedArray with length of `numrows`-valueconst typedArray = new Int8Array(numrows); // typedArray.length is now 2const rows = []; // Prepare rows-arrayfor (let arrKey in typedArray) { // Iterate keys of typedArrayrows.push(<ObjectRow key={arrKey} />); // Push to an rows-array}// Return rowsreturn <tbody>{rows}</tbody>;

您可以尝试新的对于循环:

const apple = {color: 'red',size: 'medium',weight: 12,sugar: 10}for (const prop of apple.entries()){console.log(prop);}

这里是几个例子

<tbody>numrows.map((row,index) => (return <ObjectRow key={index}/>)</tbody>

除非您声明一个函数并用参数将其括起来,否则这是不可能的。在JSX表达式中,您只能编写表达式,不能像for()、声明变量或类或if()语句那样编写声明

这就是为什么函数CallExpression今天如此有兴致。我的建议是:习惯它们。这是我要做的:

const names = ['foo', 'bar', 'seba']const people = <ul>{names.map(name => <li>{name}</li>)}</ul>

过滤:

const names = ['foo', undefined, 'seba']const people = <ul>{names.filter(person => !!person).map(name => <li>{name}</li>)}</ul>

if():

var names = getNames()const people = {names && names.length &&<ul>{names.map(name => <li>{name}</li>)}</ul> }

如果-否则:

var names = getNames()const people = {names && names.length ?<ul>{names.map(name => <li>{name}</li>)}</ul> : <p>no results</p> }

您可以像下面这样创建一个新组件:

将键和数据传递给ObjectRow组件,如下所示:

export const ObjectRow = ({key,data}) => {return (<div>...</div>);}

创建一个新的组件ObjectRowList来充当数据的容器:

export const ObjectRowList = (objectRows) => {return (<tbody>{objectRows.map((row, index) => (<ObjectRow key={index} data={row} />))}</tbody>);}
render() {const elements = ['one', 'two', 'three'];
const items = []
for (const [index, value] of elements.entries()) {items.push(<li key={index}>{value}</li>)}
return (<div>{items}</div>)}

使用map函数。

<tbody>{objects.map((object, i) =>  <ObjectRow obj={object} key={i} />)}</tbody>

我见过一个人/上一个答案在数组中使用. concat(),但不是这样…

我使用conat添加到字符串中,然后通过jQuery选择器在元素上呈现JSX内容:

let list = "<div><ul>";
for (let i=0; i<myArray.length; i++) {list = list.concat(`<li>${myArray[i].valueYouWant}</li>`);}
list = list.concat("</ul></div>);
$("#myItem").html(list);

我不确定这是否适用于您的情况,但通常[map][1]是一个很好的答案。

如果这是你的for循环代码:

<tbody>for (var i=0; i < objects.length; i++) {<ObjectRow obj={objects[i]} key={i}>}</tbody>

你可以用map函数这样写:

<tbody>{objects.map(function(object, i){return <ObjectRow obj={object} key={i} />;})}</tbody>

objects.map是做循环的最佳方式,objects.filter是过滤所需数据的最佳方式。过滤后的数据将形成一个新的数组,objects.some是检查数组是否满足给定条件的最佳方式(它返回布尔值)。

随着时间的推移,语言变得越来越成熟,我们经常会偶然发现这样的常见问题。问题是循环一个组件n次。

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

其中,n-是您想要循环的次数。item将是未定义的,index将像往常一样。此外,ESLint不鼓励使用数组索引作为键。

但是你的优势是不需要在之前初始化数组,最重要的是避免了for循环…

为了避免项目未定义带来的不便,您可以使用_,以便在打印时忽略它,并且不会抛出任何打印错误,例如

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

也许今天最大开发人员的标准,使用这样的结构:

 let data = [{id: 1,name: "name1"},{id: 2,name: "name2"},{id: 3,name: "name3"},{id: 100,name: "another name"}];
export const Row = data => {return (<tr key={data.id}><td>{data.id}</td><td>{data.name}</td></tr>);};
function App() {return (<table><thead><tr><th>Id</th><th>Name</th></tr></thead><tbody>{data.map(item => Row(item))}</tbody></table>);}

在JSX中,在超文本标记语言或此处的任何代码中编写JavaScript操作,#0,使用单花括号和map函数。

并看到以下输出这里

简单的方法

您可以将numrow放在中并使用地图而不是进行循环:

{this.state.numrows.map((numrows , index) => {return (<ObjectRowkey={index}/>

有多种方法可以在JSX中循环

  1. 使用进行循环

    function TableBodyForLoop(props) {const rows = []; // Create an array to store list of tr
    for (let i = 0; i < props.people.length; i++) {const person = props.people[i];// Push the tr to array, the key is importantrows.push(<tr key={person.id}><td>{person.id}</td><td>{person.name}</td></tr>);}
    // Return the rows inside the tbodyreturn <tbody>{rows}</tbody>;}
  2. 使用ES6数组地图方法

    function TableBody(props) {return (<tbody>{props.people.map(person => (<tr key={person.id}><td>{person.id}</td><td>{person.name}</td></tr>))}</tbody>);}
    

完整示例:https://codesandbox.io/s/cocky-meitner-yztif

以下React Docs会有所帮助

有趣的是,人们如何使用更新的语法或不常见的方法来创建数组来给出“创造性”的答案。在我使用JSX的经验中,我见过这些技巧只被没有经验的React程序员使用。

解决方案越简单-对未来的维护者越好。而且由于React是一个Web框架,通常这种类型的(表)数据来自API。因此,最简单也是最实用的方法是:

const tableRows = [{id: 1, title: 'row1'},{id: 2, title: 'row2'},{id: 3, title: 'row3'}]; // Data from the API (domain-driven names would be better of course)...
return (tableRows.map(row => <ObjectRow key={row.id} {...row} />));


你只能在JSX元素中编写JavaScript表达式,所以进行循环无法工作。你可以先将元素转换为数组,然后使用map函数来呈现它:

<tbody>{[...new Array(numrows)].map((e) => (<ObjectRow/>))}</tbody>

在map中包含JSX内容可能是笨重的语法。相反,您可以这样做:

const ObjectRow = ({ ... }) => <tr key={}>...</tr>
const TableBody = ({ objects }) => {return <tbody>{objects.map(ObjectRow)}</tbody>;}

这是简写

{ objects.map(object => ObjectRow(object))

如果ObjectRow设置为采用与object中相同的键,这将非常有效。

注意-在呈现ObjectRow时,您可能需要设置key prop。它不能通过函数调用传入。


更多笔记-我遇到了一些地方,这种技术是一个坏主意。例如,它没有经过正常的创建组件路径,也不会默认prop值,所以要小心。尽管如此,了解它很方便,有时也很有用。

const numrows = [1, 2, 3, 4, 5];
cosnt renderRows = () => {return numros.map((itm,index) => <td key={index}>{itm}</td>)}
return <table>............<tr>{renderRows()}</tr></table>

Array.from是最好的方法。如果您想创建一个具有一定长度的JSX数组。

function App() {return (<tbody>{Array.from({ length: 10 }, (_, key) => (<ObjectRow {...{ key }} />))}</tbody>);}

上面的示例适用于您没有数组的情况,因此如果您有数组,您应该将其映射到JSX中,如下所示:

function App() {return (<tbody>{list.map((item, key) => (<ObjectRow {...{ key }} />))}</tbody>);}

在渲染或任何函数中,在返回之前,您可以使用变量来存储JSX元素。就像这样-

const tbodyContent = [];for (let i=0; i < numrows; i++) {tbodyContent.push(<ObjectRow/>);}

像这样在你的tbody中使用它:

<tbody>{tbodyContent}</tbody>

但我更喜欢地图而不是这个。

function PriceList({ self }) {let p = 10000;let rows = [];for(let i=0; i<p; i=i+50) {let r = i + 50;rows.push(<Dropdown.Item key={i} onClick={() => self.setState({ searchPrice: `${i}-${r}` })}>{i}-{r} &#8378;</Dropdown.Item>);}return rows;}
<PriceList self={this} />

如果你习惯了Angular,想要一个更像React的方法:

尝试使用这个简单的组件与自动散列和可选的trackBy类似于Angular的。

用法:

<For items={items}>{item => <div>item</div>}</For>

自定义键/trackBy:

<For items={items} trackBy={'name'}>{item => <div>item</div>}</For>

定义:

export default class For<T> extends Component<{ items: T[], trackBy?: keyof T, children: (item: T) => React.ReactElement }, {}> {render() {return (<Fragment>{this.props.items.map((item: any, index) => <Fragment key={this.props.trackBy ?? item.id ?? index}>{this.props.children(item)}</Fragment>)}</Fragment>);}}

React开发工具:

在此输入图片描述

您可以直接在JSX中执行相同的操作,使用map而不是for-of循环:

render: function() {const items = ['one', 'two', 'three'];return (<ul>{items.map((value, index) => {return <li key={index}>{value}</li>})}</ul>)}

只要做这样的事情:

<tbody>{new Array(numRows).fill("", 0, numRows).map((p, i) => <YourRaw key={i} />)}</tbody>

如果你真的想要一个进行循环等效(你有一个数字,而不是一个数组),只需使用#0来自Lodash

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

import range from 'lodash/range'
range(4);// => [0, 1, 2, 3]
range(1, 5);// => [1, 2, 3, 4]

您可以在React进行循环中使用. map()。

<tbody>{ newArray.map(() => <ObjectRow />) }</tbody>

您可以执行以下操作来重复组件numrows

<tbody>{Array(numrows).fill(<ObjectRow />)}</tbody>

试试这个

<tbody>{new Array(numrows).map((row,index)=><ObjectRow key={***someThingUniqe***}/>)} //don't use index as key</tbody>

如果你想知道为什么你不应该使用索引作为键在反应检查这个

使用map到循环

 Array.map(arrayItem => {return <ObjectRow arrayItem={arrayItem}/> // pass array item in component})

这是我到目前为止在大多数项目中使用的:

const length = 5;...<tbody>{Array.from({ length }).map((_,i) => (<ObjectRow key={i}/>))}</tbody>

请试试这个

<tbody>{Array.apply(0, Array(numrows)).map(function (x, i) {return <ObjectRow/>;})}</tbody>

{[...Array(numrows)].map((x, i) =><ObjectRow/>)}

If you want to add some amount of the same React Component of DOM elements this answer is for you

创建第N个长度数组(选择所需的长度)并调用方法map

SomeComponent.jsx/.tsx

No matter which extension you use in this situation

import React from "react"
let length = 10 (for example)
const SomeComponent = () => (<div>{new Array(length).fill(null).map(item => {return  <ObjectRow/>})}</div>
)

你可以在reactjs中使用. map()for循环

    <tbody>{items.map((value, index) => {return <li key={index}>{value}</li>})}</tbody>)

一个单行线(假设numrow是一个数字):

<tbody>{Array(numrows).fill().map(function (v, i) {return <ObjectRow/>})}</tbody>

下面的代码将帮助您在JSX中创建循环,并传递唯一的密钥道具

import React, { Children, Fragment } from 'react';
export const ObjectRow = ({ data }) => (<div><Fragment>{data}</Fragment></div>);

/** Wrapping your list inside React.Children.toArray allows you to notpass unique key props.It will be dynamically generated from Virtual Dom to Real Dom */
export const ObjectRowListComponent = (objectRows) => (<tbody>{Children.toArray(objectRows.map((row) => <ObjectRow data={row} />))}</tbody>);

你可以从numRow创建数组并映射它

像这样:

        <tbody>{Array.from({ length: numrows }).map((_,i)=><ObjectRow key={i}/>)</tbody>