在React JSX中循环

时间:2014-04-05 05:29:28

标签: javascript reactjs

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

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

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

74 个答案:

答案 0 :(得分:968)

想想它就像你只是调用JavaScript函数一样。您不能使用for循环,其中函数调用的参数将为:

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

查看函数tbody如何作为参数传递for循环,当然这是语法错误。

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

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

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

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

顺便说一句,我的JavaScript示例几乎就是JSX转换的例子。到处使用Babel REPL来了解JSX的工作原理。

答案 1 :(得分:765)

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

如果这是带有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>

ES6语法:

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

答案 2 :(得分:381)

如果您还没有像{FakeRainBrigand的答案那样拥有map()的数组,并想要内联这样,那么源布局对应的输出比@ SophieAlpert更接近输出回答:

使用ES2015(ES6)语法(扩展和箭头功能)

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

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

Re:与Babel一起转发,caveats page表示传播需要Array.from,但目前(v5.8.23)传播实际情况时似乎并非如此Array {1}}。我有一个documentation issue可以澄清这一点。但请自担风险或使用polyfill。

Vanilla ES5

Array.apply

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

Inline IIFE

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语法&amp; Array方法

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

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

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

fill()

在所有情况下,key attr都会缓解开发版本的警告,但在儿童中无法访问。如果您希望子项中的索引可用,则可以传递额外的attr。请参阅Lists and Keys进行讨论。

答案 3 :(得分:68)

使用数组地图功能是循环数组元素并在 React 中根据它们创建组件的常用方法,这是一个在 JSX 中执行循环非常高效且整洁的循环的好方法,它是唯一的方法,但<强烈的>首选方式。

另外,根据需要,不要忘记每次迭代都有唯一键地图功能会从0创建唯一索引,但不建议使用生成的索引,但如果您的值是唯一的,或者如果有唯一键,则可以使用它们:

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

如果你不熟悉数组上的map函数,那么来自 MDN 的几行:

  

map为一个元素中的每个元素调用一次提供的回调函数   数组,按顺序,并从结果中构造一个新数组。打回来   仅对已分配值的数组的索引调用,   包括undefined。它没有被称为缺少的元素   数组(即从未设置过的索引,已经过了   已删除或从未分配过值。)

     使用三个参数调用

回调:元素的值,   元素的索引和遍历的Array对象。

     

如果提供thisArg参数进行映射,则将其用作   回调这个值。否则,undefined值将用作   它的这个价值。回调最终可以观察到这个值   根据通常的规则确定这一点   通过功能。

     

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

答案 4 :(得分:68)

只需使用带有ES6语法的地图 数组方法:

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

别忘了key财产。

答案 5 :(得分:42)

如果您已经使用了lodash,则_.times功能非常方便。

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}>
                            <Select onSelect={this.onSelect}>
                                <option value="1">bacon</option>
                                <option value="2">cheez</option>
                            </Select>
                        </li>
                    )}
                </ol>
            </div>
        );
    }
}

答案 6 :(得分:33)

您也可以在返回区外提取:

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

    return (<tbody>{rows}</tbody>);
}

答案 7 :(得分:23)

我知道这是一个旧线程,但您可能想要签出http://wix.github.io/react-templates/,它允许您使用jsx样式模板进行反应,并使用一些指令(例如rt-repeat)。

您的示例,如果您使用react-templates,则为:

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

答案 8 :(得分:20)

如果numrows是一个数组,那很简单。

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

React中的数组数据类型非常好,数组可以支持新数组,并支持过滤,减少等。

答案 9 :(得分:18)

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

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

您可以在GitHub上查看完整的FeatureList codefeatures fixture is listed here

答案 10 :(得分:14)

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

我的回答旨在巩固已经呈现的所有精彩方式:

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

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

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

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

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 for循环:

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

答案 11 :(得分:14)

让我们说你们州里有一系列物品:

[{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>

答案 12 :(得分:13)

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

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 here
 return (
  <ObjectRow/>
)

}
  return(
   <tbody>{mapItem.map(singleItem)}</tbody>
  )
}

答案 13 :(得分:12)

我用这个:

gridItems = this.state.applications.map(app =>
                            <ApplicationItem key={app.Id} app={app } />
                            );
PD:永远不要忘记密钥,否则你会收到很多警告!

答案 14 :(得分:12)

只需使用.map()循环整个集合,并在每次迭代时返回包含道具的<ObjectRow>项。

假设objects是某个地方的数组......

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

答案 15 :(得分:12)

ES2015 / Babel可能使用生成器函数来创建JSX数组:

function* jsxLoop(times, callback)
{
    for(var i = 0; i < times; ++i)
        yield callback(i);
}

...

<tbody>
    {[...jsxLoop(numrows, i =>
        <ObjectRow key={i}/>
    )]}
</tbody>

答案 16 :(得分:12)

如果您选择在渲染方法的 return()内进行转换,则最简单的选项是使用 map()方法。使用map()函数将数组映射到JSX语法,如下所示(使用ES6语法)。

内部组件

<tbody> { objectArray.map((object, index) => <ObjectRow key={index} object={object}>) } </tbody>

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

  

警告:数组或迭代器中的每个子节点都应该有   一个独特的关键&#34;丙

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

内部ObjectRow组件

const { object } = this.props

const object = this.props.object

这应该会将您从父组件传递的对象提取到 ObjectRow 组件中的变量object。现在,您可以根据自己的目的吐出该对象中的值。

参考文献:

map() method in Javascript

ECMA Script 6 or ES6

答案 17 :(得分:10)

您的JSX代码将编译为纯JavaScript代码,任何标记都将被ReactElement对象替换。在JavaScript中,您无法多次调用函数来收集返回的变量。

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

或者您可以使用Array.prototype.map since JavaScript ES5来处理这种情况。

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

答案 18 :(得分:10)

ES2015 Array.from ,带有地图功能+键

如果您没有.map(),则可以Array.from()使用mapFn重复元素:

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

答案 19 :(得分:10)

你当然可以用另一个答案所建议的.map来解决。如果你已经使用了babel,你可以考虑使用jsx-control-statements 它们需要一些设置,但我认为它在可读性方面是值得的(特别是对于非反应开发人员)。 如果使用linter,还有eslint-plugin-jsx-control-statements

答案 20 :(得分:10)

我倾向于赞成编程逻辑发生在import _ from 'lodash'; ... const TableBody = ({ objects }) => { const objectRows = objects.map(obj => <ObjectRow object={obj} />); return <tbody>{objectRows}</tbody>; } 的返回值之外的方法。这有助于保持实际呈现的内容易于理解。

所以我可能会这样做:

import mod = require('./MyModule');

console.log(mod.name);

不可否认,这是一个很少的代码,内联它可能会正常工作。

答案 21 :(得分:9)

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

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

    中循环

    方法1

     let container =[];
        let arr = [1,2,3] //can be anything array, object 
    
        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, object 
              arr.forEach((val,index)=>{
                container.push(<div key={index}>
                               val
                               </div>)
                             });
                        return container;     
            })()}
    
         </div>
      </div>
    )
    

答案 22 :(得分:9)

要循环多次并返回,可以在frommap的帮助下实现:

CompanyId | Date (company has no data)
----------+-----------------------------
 x        | 2017-07-14
 y        | 2017-07-05

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

答案 23 :(得分:7)

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

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

答案 24 :(得分:7)

我像

一样使用它
<tbody>
{ numrows ? (
   numrows.map(obj => { return <ObjectRow /> }) 
) : null}
</tbody>

答案 25 :(得分:7)

这是一个简单的解决方案。

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

不需要映射和复杂代码。您只需要将行推送到数组并返回值以进行渲染。

答案 26 :(得分:6)

您还可以使用自动调用功能:

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

           })()}
        </tbody>

答案 27 :(得分:6)

很棒的问题。

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

定义一个返回JSX的函数:

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

//... in JSX

<tbody>
    {myExample()}
</tbody>

答案 28 :(得分:5)

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

答案 29 :(得分:5)

以下是React doc的示例: https://facebook.github.io/react/docs/jsx-in-depth.html#javascript-expressions-as-children

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

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

答案 30 :(得分:5)

您可以执行以下操作:

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

答案 31 :(得分:4)

下面是在迭代对象数组或普通数组时可以采取的应对措施

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

<tbody>
    { rows }
</tbody>

OR

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进行返回或不返回

.return的地图

   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>

答案 32 :(得分:4)

你可以直接在 JSX 中做同样的事情,使用 map 而不是 for-of 循​​环:

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

答案 33 :(得分:4)

即使这段代码也可以完成相同的工作。

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

答案 34 :(得分:4)

我不确定这是否适合您的情况,但通常[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是检查数组是否满足给定条件(返回布尔值)的最佳方法。

答案 35 :(得分:3)

用于打印数组值(如果您没有键值参数),然后使用以下代码-

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

答案 36 :(得分:3)

您可以尝试使用新的for循环

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

以下是一些示例:https://flaviocopes.com/react-how-to-loop/

答案 37 :(得分:3)

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

答案 38 :(得分:3)

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

int size = 4 * renderBufferHeight * renderBufferWidth;
unsigned char *data2 = new unsigned char[size];
glReadPixels(0, 0, renderBufferWidth, renderBufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, data2);

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

答案 39 :(得分:3)

好的,你走了。

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

所有你需要做的,只需映射你的数组并返回你想呈现的内容,请不要忘记在返回元素中使用key

答案 40 :(得分:3)

@jacefarm如果我理解正确,你可以使用这段代码:

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

答案 41 :(得分:3)

如果你真的想在JSX中使用for循环,你可以使用IIFE。

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

答案 42 :(得分:3)

您希望向数组中添加元素并渲染元素数组 这有助于减少重新渲染组件所需的时间。

这里有一些可能有用的粗略代码:

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>])
        })
    }
}

答案 43 :(得分:3)

如果numrows是一个数组,而另一个回答最好的方法是map方法。如果不是,你只能从jsx访问它,你也可以使用这个ES6方法:

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

答案 44 :(得分:3)

如果您真的想要一个等效的 for 循环(您只有一个数字,而不是一个数组),只需使用 range from Lodash

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

import range from 'lodash/range'

range(4);
// => [0, 1, 2, 3]

range(1, 5);
// => [1, 2, 3, 4]

答案 45 :(得分:2)

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} />

答案 46 :(得分:2)

如果你习惯了 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 开发工具:

Enter image description here

答案 47 :(得分:2)

在地图中包含jsx可能是笨拙的语法,相反,您可以这样做。

const ObjectRow = ({ ... }) => <tr key={}>...</tr>

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

这是速记

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

如果将ObjectRow设置为使用object中的相同键,则效果很好。

注意-渲染ObjectRow时,您可能需要设置key道具,无法通过函数调用将其传递。


更多说明-我已经遇到了很多使用此技术的主意。例如,它不会通过常规的create component路径,并且不会使用默认的prop值,因此请当心。尽管如此,了解还是有用的。

答案 48 :(得分:2)

您只能在JSX元素中编写JS表达式,因此对于循环无法正常工作,您可以先将元素转换为数组,然后使用map函数进行渲染

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

答案 49 :(得分:2)

人们如何使用较新的语法或不常见的创建数组的方式给出“创造性”答案,这很有趣。在使用JSX的经验中,我看到了这些技巧仅由没有经验的React程序员使用。

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

const tableRows = [
   {id: 1, title: 'row1'}, 
   {id: 2, title: 'row2'}, 
   {id: 3, title: 'row3'}
]; // data from API (domain-driven name would be better ofc)

...

return (
   tableRows.map(row => <ObjectRow key={row.id} {...row} />)
);

答案 50 :(得分:2)

随着时间的流逝,语言变得越来越成熟,而且我们经常偶然遇到这样的常见问题。问题是要循环一个组件n次。

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

其中,n-是您要循环的次数。 item是未定义的,而index将照常。  另外,不鼓励使用数组索引作为键。

但是您的优点是不需要在初始化数组之前进行初始化,最重要的是避免了for循环...

答案 51 :(得分:2)

jsx中的

循环非常简单,试试这个。

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

答案 52 :(得分:2)

您可以如下创建新组件:

像这样将密钥和数据传递到您的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>
    );
}

答案 53 :(得分:2)

React元素是简单的JS,所以你可以遵循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警告:数组或迭代器中的每个子节点都应该有   一个独特的关键&#34;支柱。检查ComponentName的呈现方法。看到   &#34;连结&#34;了解更多信息。

答案 54 :(得分:2)

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

答案 55 :(得分:2)

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

答案 56 :(得分:2)

Using map in react are best practices for iterate over an array.

To prevent some errors with es6 synthax map is used like this in react :

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

Here you call a Component so you don't need to put parenthesis after the arrow.

But you can be make this too :

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

or :

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

I say that because if you put a bracket "{}" after the arrow react will not throw error and will display a whitelist.

答案 57 :(得分:2)

每当您需要在JSX中放置任何JavaScript代码时,您应该放置{},而不是将JavaScript代码放在这些括号中。 就这么简单。

这样你就可以在jsx / react内循环。

说:

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

示例:

   <tbody>
    { items.map( ( item ) > { console.log(item) }) } // items looping using map
  </tbody>

答案 58 :(得分:2)

我已经找到了另一种解决方案来跟踪地图 渲染

 <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>
      <button
        onClick={this.deletMovie.bind(this, movies._id)}
        className="btn btn-danger"
      >
        Delete
      </button>
    </td>
  </tr>
));
return bodyarea;
}

此示例轻松解决了许多问题

答案 59 :(得分:1)

除非声明了一个函数并用参数将其括起来,否则是不可能的。在JSXExpression中,您只能编写EXPRESSIONS,而不能编写STATEMENTS,例如for(),声明变量或类或if()语句。

这就是为什么函数CallExpressions在今天如此流行的原因。我的建议,请习惯他们。这就是我要做的:

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> }

希望有帮助

答案 60 :(得分:1)

就做这样的事情:

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

答案 61 :(得分:1)

你必须用JSX写作

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

答案 62 :(得分:1)

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

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

这有点含糊,但是您可以换出任何数组的数据。这将为您提供每个项目的表格行和表格项目。如果您在数组的每个节点中不止一件事,那么您将希望通过执行以下操作来专门针对此目标:

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

在这种情况下,您将需要用不同的td包围它,并以不同的方式排列上一个示例。

答案 63 :(得分:1)

这里发布了许多解决方案,包括迭代数组和生成jsx元素。它们都很好,但是它们都直接在循环中使用了索引。建议我们使用数据中的唯一ID作为键,但是当我们没有数组中每个对象的唯一ID时,我们将使用索引作为键,但是不建议您直接使用索引作为键。

我们为什么要使用.map还有另一件事,为什么不使用.foEach,因为.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作为键版本时,会返回return

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

答案 64 :(得分:1)

也许tody最大的开发人员标准使用这种结构,例如:

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

在html中的JSX中,您的javascript操作或此处的任何代码 {data.map(item => Row(item))} 在已知更多map的map函数内使用单个花括号

并查看以下输出here

答案 65 :(得分:1)

如果您想使用存储为Integer值的特定行数,则可以提供更直接的解决方案。借助typedArrays,我们可以通过以下方式实现所需的解决方案。

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

答案 66 :(得分:1)

使用地图功能会为您提供帮助。

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

答案 67 :(得分:0)

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>

答案 68 :(得分:0)

有多种方法可以在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 important
    rows.push(
      <tr key={person.id}>
        <td>{person.id}</td>
        <td>{person.name}</td>
      </tr>
    );
  }

  // return the rows inside the tbody
  return <tbody>{rows}</tbody>; 
}

  1. 使用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将有所帮助

答案 69 :(得分:0)

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

console.log(typeof(parseInt((0.1 + 0.2).toFixed(1)))); // number
console.log((0.1 + 0.2).toFixed(1) == 0.3); // true
console.log((parseInt((0.1 + 0.2).toFixed(1))) === 0.3); // false

像这样在身体内部使用它:

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

但是我更喜欢地图。

答案 70 :(得分:0)

简单方式 您可以将数字置于状态并使用map而不是for循环:

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

答案 71 :(得分:0)

我看到上面的一个人/答案在数组中使用.concat(),但不是这样...

我已经使用concat添加到字符串,然后仅通过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);

答案 72 :(得分:0)

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

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

答案 73 :(得分:0)

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

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