Петля всередині React JSX


1278

Я намагаюся зробити щось подібне в React JSX(де ObjectRow - окремий компонент):

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

Я розумію і розумію, чому це не вірно JSX, оскільки JSXкарти для функціонування дзвінків. Однак, виходячи з землі шаблону і будучи новим JSX, я не впевнений, як би досягти вищезазначеного (додаючи компонент кілька разів).


38
Важливо зазначити, що в JSX вам потрібні {} теги навколо вашого синтаксису JavaScript. Це може допомогти facebook.github.io/react/docs/… .
Ісая Грей

30
let todos = this.props.todos.map((todo) => {return <h1>{todo.title}</h1>})
OverCoder


@OverCoder, чому б ти поставив ціле повернення в тег {}, це буде => return <h1> {todo.title} </h1> Чи не так?
pravin poudel

1
@pravinpoudel насправді ця відповідь стара, більше схожа на let todos = this.props.todos.map(t => <h1>{t.title}</h1>):)
OverCoder

Відповіді:


1205

Подумайте про це так, як ви просто викликаєте функції 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.


3
Можливо, компілятор змінився, оскільки цей приклад, здається, не компілюється в компіляторі jsx , але використання карти, як у відповіді FakeRainBrigand нижче, здається, складено правильно.
рів

9
Я можу пообіцяти, що останній приклад все ще правильно збирається на останньому компіляторі JSX.
Софі Альперт

3
Це добре працює. Відповідь FakeRainBrigand працює для простої ітерації масиву, але ця відповідь є обов'язковою для сценаріїв, де ви не можете використовувати map(наприклад, у вас немає колекції, що зберігається у змінній).
Келвін

52
React потребує ефективного оновлення дому, у цьому випадку батько повинен призначити keyкожну дитину. REF: facebook.github.io/react/docs/…
qsun

7
Цей приклад спрацює, але він пропускає деякі важливі біти, такі як keyвластивість, а також стиль коду, який насправді не використовується в кодах баз React. Будь ласка, розгляньте цю відповідь stackoverflow.com/questions/22876978/loop-inside-react-jsx/… як правильну.
okonetchnikov

865

Не впевнений, чи це буде підходити для вашої ситуації, але часто карта підходити є гарною відповіддю.

Якщо це був ваш код із циклом for:

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

43
Карта має більше сенсу, якщо iteratee є масивом; Цикл циклу підходить, якщо це число.
Шепітер коду

26
<tbody>{objects.map((o, i) => <ObjectRow obj={o} key={i}/>}</tbody>використовуючи підтримку Reactify ES6 або Babel.
Distortum

3
+1. Я навіть використовую це з ul (не упорядкований список). <ul> {objects.map((object:string,i:number)=>{ return <li>{object}</li> })} </ul>використовуючи TypeScript
Roberto C Navarro

5
це чудово, але ви не можете for..in
Деймон

4
Майте на увазі, що порядок клавіш довільний при використанні Object.keys. Я вважаю, що зберігання порядку ключів окремо працює добре, а також порядок на об'єкті буквально, якщо необхідно. Це дозволяє мені писати такий код, якthis.props.order.map((k)=><ObjectRow key={k} {...this.props.items[k]} />)
tgrrr

443

Якщо у вас ще немає масиву, який map()би подобався відповіді @ FakeRainBrigand, і ви хочете вкласти це так, щоб макет джерела відповідав висновку ближче, ніж відповіді @ 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>

Вбудований 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>
  );
}

За допомогою синтаксису та Arrayметодів ES2015

З цим Array.prototype.fillви можете зробити це як альтернативу використанню спред, як показано вище:

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

(Я думаю, ви насправді можете пропустити будь-який аргумент fill(), але я не на 100% з цього приводу.) Завдяки @FakeRainBrigand за виправлення моєї помилки в попередній версії fill()рішення (див. Версії ).

key

У всіх випадках keyattr знімає попередження при створенні розвитку, але не доступне для дитини. Ви можете передати додатковий attr, якщо хочете, щоб індекс був доступний дитині. Див. Списки та ключі для обговорення.


2
Про що yield? Проштовхування елементів у проміжний масив є якось негарним, коли у нас є генератори. Вони працюють?
mpen

2
@ Марк Я не знаю, що генератори тут дійсно застосовні. Ключовим для цього в контексті JSX є вираз, який повертає масив. Тож якби ви хотіли якось використовувати генератор, ви, мабуть, все-таки поширили його, і він, мабуть, буде більш багатослівним, ніж рішення, засновані на ES2015.
JMM

2
Як це більш багатослівно? І чому б JSX не прийняв будь-який ітерабельний, а не лише масив?
mpen

2
@Mark Це дійсно менш багатослівний, ніж я використовував приклад IIFE (ES5) IIFE, але він набагато більш багатослівний, ніж [...Array(x)].map(() => <El />))версія, яка, на мою думку, є найелегантнішою, і чому я її показав. Re: друге питання, це чудовий момент. Здається, що в JSX нічого не виключає, тому це залежить від того, що реагує чи інший споживач перетвореного JSX з аргументами дітей, чого я не міг сказати, не дивлячись на джерело. Чи ти знаєш? Це інтригуюче питання.
JMM

3
@corysimmons Класно, дякую за інформацію про fill(). Зараз я пам’ятаю, що причиною, коли я вагався, є питання про те, як необов’язковість параметрів вказана у специфікації ES (треба вивчити це колись). Кома - це лише спосіб схилити елемент масиву - у цьому випадку перший. Ви можете це зробити, якщо ви хочете, щоб індекси були від 1..length масиву, який ви поширюєте, а не 0..length-1 масиву спред (тому що вилучені елементи просто сприяють довжині масиву і don ' t мати відповідне властивість).
JMM

85

Просто використовуючи метод масиву map з синтаксисом ES6:

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

Не забувайте про keyмайно.


Я додаю випадкову клавішу 'Math.random ()' замість id, вона не працює нормально, коли setState всередині дітей маєте ідею чому?
Олівер Д

82

Використання карти масиву функції - це дуже поширений спосіб провести цикл через масив елементів та створити компоненти відповідно до них у React , це чудовий спосіб зробити цикл, який є досить ефективним та охайним способом робити петлі в JSX , це не єдиний спосіб це зробити, але бажаний спосіб.

Крім того, не забувайте мати унікальний ключ для кожної ітерації, якщо потрібно. Функція Map створює унікальний індекс з 0, але не рекомендується використовувати створений індекс, але якщо ваше значення унікальне або є унікальний ключ, ви можете використовувати їх:

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

Також кілька рядків з MDN, якщо ви не знайомі з функцією карти в масиві:

map викликає надану функцію зворотного виклику один раз для кожного елемента масиву для того, щоб створити новий масив з результатів. зворотний виклик викликається лише для індексів масиву, яким присвоєні значення, включаючи невизначені. Він не викликається відсутніми елементами масиву (тобто індексами, які ніколи не були встановлені, які були видалені або яким ніколи не було призначено значення).

Зворотний виклик викликається трьома аргументами: значенням елемента, індексом елемента та об'єктом масиву, що пересувається.

Якщо параметр thisArg надається для відображення, він буде використовуватися як зворотний виклик цього значення. Інакше значення undefined буде використане як його це значення. Це значення в кінцевому підсумку, яке можна побачити за допомогою зворотного дзвінка, визначається за звичайними правилами для визначення цього, що бачиться функцією.

map не мутує масив, на який він викликається (хоча зворотний виклик, якщо його викликають, може це зробити).


Array#mapце не асинхронізація!
philraj

52

Якщо ви вже використовуєте 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>
        );
    }
}

1
Array.prototype.map тут може бути чудовим варіантом, якщо ви не включаєте бібліотеку, наприклад, lodash. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… .
Ісая Грей

1
@IsaiahGrey Тільки якщо у вас вже є масив. Іноді просто хочеться повторити матеріал кілька разів.
mpen

1
звичайно! Безліч точно різних підходів залежно від фактичних даних. Я виявив, що найчастіше в процесі розробки нам вдалося вписати карту через те, як формуються дані при їх моделюванні. Чудовий приклад використання лодашу! До речі, ви використовуєте синтаксис ініціалізатора властивостей, щоб прив’язати свої методи до компонентів?
Ісая Грей

4
@IsaiahGrey Я думаю, що їх просто називають визначеннями методу
ES6

41

Ви також можете витягти поза блоком повернення:

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

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

34

Я знаю, що це стара тема, але ви, можливо, захочете перевірити шаблони React , що дозволяє використовувати реагувати шаблони у стилі jsx з кількома директивами (такими як rt-повтор).

Ваш приклад, якби ви використовували шаблони реакцій:

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

Чому для вирішення проблеми використовується додаткова бібліотека, тоді як звичайний javascript вже надав рішення з різними видами для циклу або методом Array.prototype.map? Я вже використовував обидва способи javascript у своєму поточному проекті, які добре працюють. Маючи звичку використовувати звичайні способи JavaScript, коли це можливо, допоможіть мені покращити свою майстерність у JavaScript. Я використовую додаткові бібліотеки лише тоді, коли здається, що важко знайти рішення для певних проблем, наприклад маршрутизації за допомогою React-Router.
Lex Soft

27

Існує кілька способів зробити це. Зрештою, 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-loop:

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

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

2
Чудові відповіді: різні методи, всі використовують лише звичайний javascript, який показує силу javascript, завдяки різним способам виконання подібних завдань.
Lex Soft

24

якщо numrows - це масив, і це дуже просто.

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

Тип даних масиву в React є дуже кращим, масив може підтримувати новий масив та підтримувати фільтр, зменшувати і т.д.


Це не гідна відповідь, оскільки він не використовує ключ.
kojow7

21

Є кілька відповідей, які вказують на використання mapвисловлювання. Ось повний приклад використання ітератора в компоненті FeatureList для переліку компонентів Feature на основі структури даних 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>
); 

Ви можете переглянути повний код FeatureList на GitHub. Тут представлені функції кріплення .


У роботі з даними JSON, наприклад, при отриманні даних із бази даних за допомогою API отримання, я покладаюся на використання методу Array.prototype.map. Це зручний і перевірений спосіб для цієї мети.
Lex Soft

17

Щоб циклічити кілька разів і повернутися, ви можете досягти цього за допомогою fromта map:

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

де i = number of times


Якщо ви хочете призначити унікальні ідентифікатори ключів у наданих компонентах, ви можете використовувати, React.Children.toArrayяк запропоновано в документації React

React.Children.toArray

Повертає дітям непрозору структуру даних у вигляді плоского масиву з ключами, призначеними кожній дитині. Корисно, якщо ви хочете маніпулювати колекціями дітей у своїх методах візуалізації, особливо якщо ви хочете змінити впорядкування або нарізати this.props.children перед тим, як передавати його.

Примітка:

React.Children.toArray()змінює клавіші для збереження семантики вкладених масивів при вирівнюванні списків дітей. Тобто, toArray префіксує кожну клавішу повернутого масиву, щоб ключ кожного елемента привласнювався до вхідного масиву, що містить його.

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

17

Якщо ви вирішили перетворити це всередині повернення () в візуалізації метод, самий простий варіант буде використовувати карту () метод. Зобразіть свій масив у синтаксис JSX за допомогою функції map (), як показано нижче ( використовується синтаксис ES6 ).


Всередині батьківського компонента :

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

Зверніть увагу на keyатрибут, доданий до дочірнього компонента. Якщо ви не вказали атрибут ключа, ви можете побачити наступне попередження на консолі.

Попередження: Кожна дитина в масиві чи ітераторі повинна мати унікальний реквізит "ключ".

Примітка. Одна поширена помилка, яку люди роблять, - це використовувати indexяк ключ під час ітерації, використання indexелемента як ключа є антидіаграмою, і ви можете прочитати більше про це тут . Якщо коротко, якщо це НЕ статичний список, то ніколи не використовуйте його indexяк ключ.


Тепер у компоненті ObjectRow ви можете отримати доступ до об'єкта з його властивостей.

Всередині компонента ObjectRow

const { object } = this.props

або

const object = this.props.object

Це повинно принести вам об'єкт , який передається від батьківського компонента змінної objectв ObjectRow компоненті. Тепер ви можете виплюнути значення в цьому об'єкті відповідно до свого призначення.


Список літератури:

метод map () у Javascript

Сценарій ECMA 6 або ES6


16

скажімо, у вас є масив елементів у вашій державі:

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

Я думаю, вам може знадобитися позбутися {} після карти (пункту), яка, здавалося, спрацювала для них.
Ян

15

Можливість 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>

15

... Або ви також можете підготувати масив об'єктів і відобразити його у функції, щоб мати потрібний вихід. Я вважаю за краще це, тому що це допомагає мені підтримувати хорошу практику кодування без логіки всередині повернення візуалізації.

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

15

Просто використовуйте .map()для прокручування колекції та повернення<ObjectRow> предметів з реквізитом з кожної ітерації.

Якщо припустити objects, що це десь масив ...

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

15

ES2015 Array.from допомогою функції карти + клавіша

Якщо у вас є нічого .map()вам не може використовувати Array.from()з mapфункцією повторити елементи:

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

15

Я використовую це:

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

PS: ніколи не забудьте ключ, або у вас буде багато попереджень!


Або скористайтеся індексом масиву, якщо у ваших елементів немає .Idвластивості, наприкладitems.map( (item, index) => <Foo key={index}>{item}</Foo>
kontur

13

Я схильний надавати перевагу підходу, коли логіка програмування відбувається за межами зворотного значення render. Це допомагає зберегти те, що насправді робиться легко.

Тому я, мабуть, зробив щось на кшталт:

import _ from 'lodash';

...

const TableBody = ({ objects }) => {
  const objectRows = objects.map(obj => <ObjectRow object={obj} />);      

  return <tbody>{objectRows}</tbody>;
} 

Справді, це така невелика кількість коду, що складання його може спрацювати чудово.


Великий шанувальник карти lodash для повторення через об'єкти. Я схиляюся до import { map } from 'lodash'того, що ви не імпортуєте всі функції lodash, якщо вони вам не потрібні.
Розтяжка0

У наші дні нам навіть не потрібна карта lodash - просто карта над масивом безпосередньо.
Адам Донахю

Так, але ви не можете перебирати об'єкт за допомогою es6 map(), а лише масиви. Ось що я казав, що лодаш корисний для перекидання предмета.
Розтяжка0

Я думав, ти маєш на увазі, objectsяк у списку речей, мою помилку.
Адам Донаху

12

можна, звичайно, вирішити за допомогою .map, як це запропоновано в іншій відповіді. Якщо ви вже використовуєте babel, ви можете подумати про використання jsx-control-statement. Вони потребують невеликих налаштувань, але я думаю, що це варто з точки зору читабельності (особливо це стосується розробника, який не реагує). Якщо ви використовуєте вкладиш, є також оператори eslint-plugin-jsx-control


12

Ваш JSX-код буде зібраний у чистий код JavaScript, будь-які теги будуть замінені ReactElementоб'єктами. В JavaScript ви не можете викликати функцію кілька разів для збору повернених змінних.

Це незаконно, єдиний спосіб - використовувати масив для зберігання повернених змінних функцій.

Або ви можете використовувати, Array.prototype.mapщо доступно з JavaScript ES5 для вирішення цієї ситуації.

Можливо, ми можемо написати інший компілятор, щоб відтворити новий синтаксис JSX для реалізації функції повторення так само, як і Angularng-repeat .


12

Це можна зробити декількома способами.

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

Так. У моєму поточному проекті я використовую метод 1, тобто використовуючи метод Array.prototype, forEach () для створення елемента вибору HTML, заповненого даними з бази даних. Однак я, швидше за все, заміню їх методом Array.prototype.map (), оскільки метод map виглядає більш компактно (менше коду).
Lex Soft

10

Ось просте рішення його.

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

Не потрібне відображення і складний код. Вам просто потрібно натиснути рядки на масив і повернути значення, щоб відобразити його.


Під час створення елемента вибору html цей подібний прийом був тим, хто мені спочатку прийшов до тями, тому я використовував його, хоча використовую метод forEach (). Але коли я перечитав документ React на теми «Списки та ключі», я виявив, що вони використовують метод map (), як це також показано кількома відповідями тут. Це змушує мене думати, що це найкращий спосіб. Я згоден, оскільки він виглядає більш компактно (менше коду).
Lex Soft

9

Оскільки ви пишете синтаксис Javascript всередині коду JSX, вам потрібно загорнути Javascript у фігурні дужки.

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

9

Ось зразок із документа 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 використовує Key, щоб відрізняти дані в масиві.


9

Я використовую це як

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


8

Чудове запитання.

Що я роблю, коли хочу додати певну кількість компонентів, - це використання хелперної функції.

Визначте функцію, яка повертає JSX:

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

//... in JSX

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

8

Ви також можете скористатися функцією самовикликання:

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

           })()}
        </tbody>

Використання анонімних функцій всередині візуалізації не вважається хорошою практикою реагування, оскільки ці функції потрібно заново створювати або відкидати при кожному повторному відтворенні.
Влатко Влахек

@VlatkoVlahek ви помиляєтеся з тим, що реквізити функцій відновлюються кожен цикл візуалізації, що може призвести до більш низької продуктивності у великих масштабах. Створення анонімної функції в будь-якому іншому місці не вплине на продуктивність суттєво.
Еміль Бержерон

1
@EmileBergeron Це був деякий час тому ха-ха. Я згоден, якщо це не використовується як опора, різниці немає.
Влатко Влахек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.