React JSX'in içindeki döngü


1278

React aşağıdaki gibi bir şey yapmaya çalışıyorum JSX(ObjectRow ayrı bir bileşen nerede):

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

Ben gerçekleştirmek ve bu geçerli değil anlamak JSXiçin, JSXişlev çağrılarına haritalar. Ancak, şablon topraklarından gelen ve yeni olan JSX, yukarıdakilere nasıl ulaşacağımdan emin değilim (bir bileşeni birden çok kez ekleyerek).


38
JSX'te JavaScript Sözdiziminizin etrafındaki {} etiketlere ihtiyacınız olduğunu unutmayın. Bu facebook.github.io/react/docs/… 'a yardımcı olabilir .
Isaiah Gray

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


@OverCoder neden tüm dönüşü {} etiketine koymak istersiniz => dönüş <h1> {todo.title} </h1> Değil mi?
pravin poudel

1
@pravinpoudel aslında cevap eski, daha çok let todos = this.props.todos.map(t => <h1>{t.title}</h1>):)
OverCoder

Yanıtlar:


1205

Sadece JavaScript işlevlerini çağırıyormuşsunuz gibi düşünün. forBir işlev çağrısının bağımsız değişkenlerinin gideceği bir döngü kullanamazsınız :

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

İşlevin bağımsız değişken olarak bir döngüden nasıl tbodygeçirildiğini görün forve elbette bu bir sözdizimi hatası.

Ancak bir dizi oluşturabilir ve bunu bir argüman olarak iletebilirsiniz:

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

JSX ile çalışırken temel olarak aynı yapıyı kullanabilirsiniz:

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

Bu arada, JavaScript örneğim neredeyse tam olarak bu JSX örneğine dönüşüyor. JSX'in nasıl çalıştığını anlamak için Babel REPL ile oynayın .


3
Derleyici değişmiş olabilir, çünkü bu örnek jsx derleyicisinde derlenmiş gibi görünmüyor , ancak haritayı FakeRainBrigand'ın aşağıdaki cevabındaki gibi kullanmak doğru bir şekilde derlenmiş gibi görünüyor.
rav

9
Son örneğin hala en son JSX derleyicisinde doğru bir şekilde derlendiğine söz verebilirim.
Sophie Alpert

3
Bu iyi çalışıyor. FakeRainBrigand'ın cevabı basit dizi yinelemesi için çalışır, ancak bu cevap kullanamayacağınız senaryolar için bir zorunluluktur map(örneğin, bir değişkente depolanan koleksiyonunuz yok).
Kelvin

52
React'in dom'i verimli bir şekilde güncellemesi gerekir, bu durumda ebeveyn keyher çocuğa bir atamalıdır . REF: facebook.github.io/react/docs/…
qsun

7
Bu örnek işe yarayacaktır, ancak keyözellik gibi bazı önemli bitleri ve React kod tabanlarında gerçekten kullanılmayan bir kod stilini kaçırır . Lütfen bu cevabı stackoverflow.com/questions/22876978/loop-inside-react-jsx/… 'ı doğru olarak düşünün .
okonetchnikov

866

Bunun durumunuz için işe yarayıp yaramayacağından emin değilim, ancak genellikle harita iyi bir cevaptır.

Bu, for döngüsüne sahip kodunuzsa:

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

Harita ile şöyle yazabilirsiniz :

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

ES6 sözdizimi:

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

43
Yineleme bir dizi ise harita daha anlamlı olur; For döngüsü, bir sayı ise uygundur.
Code Whisperer

26
<tbody>{objects.map((o, i) => <ObjectRow obj={o} key={i}/>}</tbody>Reactify'nin ES6 desteğini veya Babel'i kullanarak.
Distortum

3
+1. Bunu bir ul (sırasız liste) ile bile kullanıyorum. <ul> {objects.map((object:string,i:number)=>{ return <li>{object}</li> })} </ul>kullanan TypeScript
Roberto C Navarro

5
bu harika, ama bir nesnenin üzerine harita for..in
Damon

4
Object.keys kullanırken anahtarların sırasının keyfi olduğunu unutmayın. Anahtarların sırasını ayrı olarak saklamanın ve gerekirse nesne değişmezindeki sıralamanın iyi çalıştığını görüyorum. Bu benim gibi kod this.props.order.map((k)=><ObjectRow key={k} {...this.props.items[k]} />)
yazmama

443

map()@ FakeRainBrigand'ın cevabını beğenecek bir diziniz yoksa ve bunu satır içi yapmak istiyorsanız, kaynak düzeni @ SophieAlpert'in cevabından daha yakın çıktıya karşılık gelir:

ES2015 (ES6) sözdizimi ile (forma ve ok işlevleri)

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

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

Re: Babel ile nakil, uyarılar sayfasıArray.from yayılması için gerekli olduğunu söylüyor , ancak şu anda ( v5.8.23) gerçek bir yayılırken böyle görünmüyor Array. Bunu açıklığa kavuşturmak için açık bir dokümantasyon sorunum var. Ancak kendi sorumluluğunuzdadır veya çoklu dolgu kullanın.

Vanilya ES5

Array.apply

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

Satır içi 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>

Diğer cevaplardan tekniklerin kombinasyonu

Kaynak düzenini çıktıya karşılık gelen şekilde tutun, ancak satır içi parçayı daha kompakt yapın:

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 sözdizimi ve Arrayyöntemleri ile

Bunu Array.prototype.fill, yukarıda gösterildiği gibi yayılmaya alternatif olarak yapabilirsiniz:

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

(Aslında herhangi bir argümanı atlayabileceğini düşünüyorum fill(), ama bunun üzerinde% 100 değilim.) @FakeRainBrigand'a, fill()çözümün önceki bir sürümündeki hatamı düzelttiği için teşekkürler (düzeltmelere bakın).

key

Her durumda, keyattr geliştirme derlemesi ile ilgili bir uyarıyı hafifletir, ancak çocukta erişilebilir değildir. Dizinin alt öğede kullanılabilir olmasını istiyorsanız fazladan bir attr iletebilirsiniz. Tartışma için Listeler ve Anahtarlar'a bakın .


2
Ne olmuş yield? Jeneratörler olduğunda elemanları bir ara diziye itmek çirkin bir şey. Onlar çalışıyorlar mı?
mpen

2
@Mark Jeneratörlerin burada gerçekten uygulanabilir olduğunu bilmiyorum. Bunun için JSX bağlamında anahtar şey, bir dizi döndüren bir ifadedir. Yani bir şekilde bir jeneratör kullanacak olsaydınız, muhtemelen onu yine de yayarsınız ve muhtemelen ES2015 tabanlı çözümlerden daha ayrıntılı olurdu.
JMM

2
Bu nasıl daha ayrıntılı? Ve neden JSX sadece dizileri değil, yinelenebilir herhangi bir şeyi kabul etmeyecek?
mpen

2
@Mark Bu gerçekten kullandığım (ES5) IIFE örneğinden daha az ayrıntılı, ama [...Array(x)].map(() => <El />))bence en zarif olan versiyondan ve neden öne çıktığımdan çok daha ayrıntılı . Re: ikinci soru, bu harika bir nokta. JSX hakkında bunu engelleyen hiçbir şey görünmüyor, bu nedenle React veya dönüştürülmüş JSX'in başka bir tüketicisinin, kaynağa bakmadan söyleyemediğim çocuk argümanlarıyla ne yaptığına bağlı. Biliyor musun? Bu ilginç bir soru.
JMM

3
@corysimmons Harika, bilgi için teşekkürler fill(). Şimdi tereddüt etmenizin, parametrelerin opsiyonelliğinin ES spesifikasyonunda nasıl belirtildiği hakkında bir soru olduğunu hatırlıyorum (o aralara bakmak zorundayım). Virgül, bir dizi öğesini elide etmenin bir yoludur - bu durumda ilk öğe. Dizinlerin forma dizisinin 0..length-1 yerine yayıldığınız dizinin 1.. uzunluğundan olmasını istiyorsanız bunu yapabilirsiniz (çünkü elenen elemanlar dizinin uzunluğuna katkıda bulunur ve t karşılık gelen bir özelliğe sahip değildir).
JMM

85

Basitçe ES6 sözdizimi ile map Array yöntemini kullanarak :

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

keyMülkiyet unutma .


Rastgele bir 'Math.random ()' anahtarı ekliyorum, yerine setState çocuklarda iyi çalışmıyor, neden herhangi bir fikrin var mı?
Oliver D

82

Kullanılması Dizi haritası işlevi bir döngü çok yaygın yoludur Array elemanlarının ve oluşturmak bileşenlerin içinde uygun Tepki , bu oldukça verimli ve içinde döngüler yapmak düzenli yoldur bir döngü yapmak için harika bir yoldur JSX , It değil sadece yapmak için bir yol, ama tercih edilen yol.

Ayrıca, gerektiği gibi her yineleme için benzersiz bir Anahtar bulundurmayı unutmayın . Harita işlevi 0'dan benzersiz bir dizin oluşturur, ancak üretilen dizinin kullanılması önerilmez, ancak değeriniz benzersizse veya benzersiz bir anahtar varsa bunları kullanabilirsiniz:

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

Ayrıca, Array'da harita işlevine aşina değilseniz , MDN'den birkaç satır :

map, bir dizideki her öğe için sırayla sağlanan geri arama işlevini bir kez çağırır ve sonuçlardan yeni bir dizi oluşturur. geri arama, yalnızca tanımsız dahil değerleri atanmış dizinin dizinleri için çağrılır. Dizinin eksik öğeleri (yani, daha önce ayarlanmamış, silinmiş veya hiç değer atanmamış dizinler) için çağrılmaz.

geri çağırma üç bağımsız değişkenle çağrılır: öğenin değeri, öğenin dizini ve geçiş yapılan Array nesnesi.

Eşlemek için bir thisArg parametresi sağlandıysa, geri çağrının bu değeri olarak kullanılır. Aksi takdirde, tanımsız değer bu değer olarak kullanılacaktır. Sonuçta geri arama ile gözlemlenebilen bu değer, bir fonksiyon tarafından görülenin belirlenmesine yönelik olağan kurallara göre belirlenir.

map, çağrıldığı diziyi değiştirmez (ancak geri çağrıldığında çağrılırsa bunu yapabilir).


Array#mapzaman uyumsuz değil!
philraj

52

Halihazırda lodash kullanıyorsanız, _.timesişlev kullanışlıdır.

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
Eğer lodash gibi bir kütüphane dahil etmiyorsanız Array.prototype.map burada harika bir seçenek olabilir. developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/… .
Isaiah Gray

1
@IsaiahGrey Yalnızca bir diziniz varsa. Bazen sadece birkaç kez tekrarlamak istersiniz.
mpen

1
Tabi, elbette! Gerçek verilere bağlı olarak çok farklı yaklaşımlar kesin. Gelişim sürecimizden daha sık olmamakla birlikte, verilerin modellenmesi halinde verilerin nasıl olduğu için haritaya sığabildiğimizi fark ettim. Lodash kullanarak harika bir örnek! Btw, yöntemlerinizi bileşenlerinize bağlamak için özellik başlatıcı sözdizimini mi kullanıyorsunuz?
Isaiah Gray

4
@IsaiahGrey Bence onlar sadece ES6 yöntem tanımları olarak
mpen

41

Ayrıca dönüş bloğunun dışına da çıkarabilirsiniz:

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

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

34

Bu eski bir iş parçacığı olduğunu biliyorum, ancak birkaç yönergeleri (rt-repeat gibi) tepki olarak jsx tarzı şablonları kullanmanıza izin verir Tepki Şablonları , satın almak isteyebilirsiniz .

Örneğin, tepki şablonları kullandıysanız:

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

Düz javascript sorunu çözmek için çeşitli for döngüsü veya Array.prototype.map yöntemi ile çözüm sunarken neden ek kitaplık kullanır? Şu anki projemde iyi çalışan her iki sade javascript yolunu zaten kullandım. Mümkün olduğunda sade javascript yollarını kullanma alışkanlığına sahip olmak, javascript'teki yeteneğimi geliştirmeme yardımcı olur. Ek kütüphaneleri yalnızca React-Router ile yönlendirme gibi belirli sorunlara çözüm bulmak zor görünüyorsa kullanıyorum.
Lex Soft

27

Bunu yapmanın birçok yolu vardır. JSX nihayetinde JavaScript'e derlenir, geçerli JavaScript yazdığınız sürece iyi olursunuz.

Cevabım burada sunulan tüm harika yolları birleştirmeyi amaçlıyor:

Bir nesne diziniz yoksa, yalnızca satır sayısı:

returnblok içinde bir oluşturma Arrayve kullanma Array.prototype.map:

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

returnblok dışında normal bir JavaScript for-loop kullanın:

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

hemen çağrılan işlev ifadesi:

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

Bir dizi nesneniz varsa

returnblok içinde , .map()her nesne bir <ObjectRow>bileşene:

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

returnblok dışında normal bir JavaScript for-loop kullanın:

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

hemen çağrılan işlev ifadesi:

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
Büyük cevaplar: çeşitli teknikler, hepsi benzer görevleri yapmanın çeşitli yolları sayesinde javascript'in gücünü gösteren düz javascript kullanır.
Lex Soft

24

numrows bir dizi ise ve çok basit.

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

React içindeki dizi veri türü çok daha iyidir, dizi yeni diziyi destekleyebilir ve filtreyi destekleyebilir, azaltabilir vb.


Bu, bir anahtardan faydalanmadığı için iyi bir cevap değildir.
kojow7

21

İfadeyi kullanmaya işaret eden birkaç cevap vardır map. İşte içinde bir yineleyici kullanarak tam bir örnektir FeatureList listesine bileşen Özelliği denilen bir JSON veri yapısını temel bileşenleri özellikleri .

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'da tüm FeatureList kodunu görüntüleyebilirsiniz. Özellikleri fikstürü burada listelenir .


JSON verileriyle uğraşırken, veritabanını getirme API'sini kullanarak veri alırken, Array.prototype.map yöntemini kullanmaya güveniyorum. Bu amaç için uygun ve kanıtlanmış bir yoldur.
Lex Soft

17

Birkaç kez döngü yapmak ve geri dönmek için, bunun yardımıyla from ve map:

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

nerede i = number of times


Oluşturulan bileşenlere benzersiz anahtar kimlikleri atamak istiyorsanız React.Children.toArray, React belgelerinde önerildiği gibi kullanabilirsiniz

React.Children.toArray

Alt öğelere opak veri yapısını, her alt öğeye atanmış tuşları olan düz bir dizi olarak döndürür. Oluşturma yöntemlerinizdeki çocuk koleksiyonlarını değiştirmek istiyorsanız, özellikle bunu yeniden sıralamak veya dilimlemek istiyorsanız, psps.children'i geçmeden önce kullanışlıdır.

Not:

React.Children.toArray()çocuk listelerini düzleştirirken iç içe dizilerin anlamını korumak için tuşları değiştirir. Diğer bir deyişle, toArray, döndürülen dizideki her bir anahtarın önekini verir, böylece her öğenin anahtarı onu içeren giriş dizisine dahil edilir.

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

17

Bunu render yönteminin return () içinde dönüştürmeyi seçerseniz, en kolay seçenek map () yöntemini kullanmak olacaktır . Aşağıda gösterildiği gibi map () işlevini kullanarak dizinizi JSX sözdizimiyle eşleyin ( ES6 sözdizimi kullanılır ).


Üst bileşen :

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

Lütfen keyalt bileşeninize eklenen özelliğe dikkat edin . Bir anahtar özellik sağlamadıysanız, konsolunuzda aşağıdaki uyarıyı görebilirsiniz.

Uyarı: Bir dizideki veya yineleyicideki her alt öğenin benzersiz bir "anahtar" desteği olmalıdır.

Not: İnsanların indexyinelediği sırada yaygın olarak yaptığı bir hata index, öğeyi anahtar olarak kullanmak bir anti-modeldir ve burada daha fazla bilgi edinebilirsiniz . Kısacası, statik bir liste DEĞİLSE asla indexanahtar olarak kullanmayın .


Artık ObjectRow bileşeninde, nesneye özelliklerinden erişebilirsiniz.

Inside ObjectRow bileşeni

const { object } = this.props

veya

const object = this.props.object

Bu size değişkene ana bileşeninden geçirilen nesne getirme gerektiğini objectde ObjectRow bileşeni. Artık bu nesnedeki değerleri amacınıza göre tükürebilirsiniz.


Referanslar :

Javascript'te map () yöntemi

ECMA Script 6 veya ES6


16

eyaletinizde bir dizi öğemiz olduğunu varsayalım:

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

Sanırım haritadan (madde) sonra benim için çalışıyor gibi görünen {} 'den kurtulmanız gerekebilir.
Ian

15

Bir ES2015 / Babel olasılığı, bir JSX dizisi oluşturmak için bir jeneratör işlevi kullanıyor:

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

...

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

15

... Veya bir nesne dizisi hazırlayabilir ve istediğiniz çıktıya sahip olacak şekilde bir işleve eşleyebilirsiniz. Bunu tercih ederim, çünkü renderın dönüşü içinde mantıksız kodlamanın iyi uygulamasını sürdürmeme yardımcı oluyor.

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()Koleksiyonunuzda dolaşmak ve <ObjectRow>her yinelemeden sahne alarak öğeleri döndürmek için kullanın .

objectsBir yerlerde bir dizi olduğunu varsayarsak ...

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

15

ES2015 Array.from , map fonksiyonu + tuşu ile

Eğer hiçbir şeyiniz .map()yoksa, elemanları tekrarlamak için Array.from()bu mapfonksiyonla birlikte kullanabilirsiniz :

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

15

Bunu kullanıyorum:

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

Not: anahtarı asla unutma yoksa çok fazla uyarı alırsın!


Veya öğeleriniz aşağıdaki .Idgibi bir özellik items.map( (item, index) => <Foo key={index}>{item}</Foo>
içermiyorsa

13

Programlama mantığının dönüş değerinin dışında olduğu bir yaklaşımı destekleme eğilimindeyim render. Bu, gerçekte neyin kolayca işlendiğinin korunmasına yardımcı olur.

Bu yüzden muhtemelen şöyle bir şey yaparım:

import _ from 'lodash';

...

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

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

Kuşkusuz, bu kadar küçük bir kod, satır içi iyi çalışabilir.


Nesneler arasında yineleme için büyük harita hayranı. Ben eğimli olacak import { map } from 'lodash'onlara rağmen gerekmiyorsa tüm lodash işlevlerini ithal edilmez yüzden.
Stretch0

Bugünlerde lodash haritasına bile ihtiyacımız yok - sadece dizi üzerinde doğrudan harita.
Adam Donahue

Evet ama es6 ile bir nesnenin içinden geçemezsiniz map(), sadece diziler. Demek istediğim, bir nesnenin üzerinde döngü için iyi oldu.
Stretch0

objectsBir şeyler listesindeki gibi olduğunu düşündüm , benim hatam.
Adam Donahue


12

JSX kodunuz saf JavaScript kodunda derlenecek, tüm etiketler ReactElementnesnelerle değiştirilecek . JavaScript'te, döndürülen değişkenlerini toplamak için bir işlevi birden çok kez çağıramazsınız.

Yasadışı, tek yol işlev döndürülen değişkenleri saklamak için bir dizi kullanmaktır.

Veya bu durumu işlemek için JavaScript ES5'ten beriArray.prototype.map mevcut olanı kullanabilirsiniz.

Belki de sadece böyle bir tekrar işlevi uygulamak için yeni bir JSX sözdizimi yeniden başka derleyici yazabilir Açısal yıllardanng-repeat .


12

Bu çok yönlü olarak yapılabilir.

  1. Yukarıda önerildiği gibi, returndizideki tüm öğeleri saklamadan önce
  2. İçeride döngü return

    Yöntem 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>
        )

    Yöntem 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>
    )

Evet. Geçerli projemde, veritabanı 1'den verilerle doldurulmuş HTML seçme öğesi oluşturmak için yöntem 1, yani Array.prototype kullanarak forEach () yöntemini kullanıyorum. Ancak, harita yöntemi daha kompakt (daha az kod) göründüğü için bunları Array.prototype.map () yöntemiyle değiştireceğim.
Lex Soft

10

İşte basit bir çözüm.

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

Eşleme ve karmaşık kod gerekmez. Sıralamak için satırları itmeniz ve değerleri oluşturmak için döndürmeniz yeterlidir.


Html select öğesi oluştururken, bu benzer teknik öncelikle aklıma gelen teknikti, bu yüzden forEach () yöntemini kullanmama rağmen kullandım. Ancak React belgesini Listeler ve Anahtarlar konularında yeniden okuduğumda, burada birkaç cevapla gösterildiği gibi map () yöntemini kullandıklarını buldum. Bu beni tercih edilen yol olduğunu düşündürüyor. Katılıyorum, çünkü daha kompakt görünüyor (daha az kod).
Lex Soft

9

JSX kodu içinde Javascript sözdizimi yazdığınız için, Javascript'inizi kaşlı ayraçlara sarmanız gerekir.

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

9

React doc'den bir örnek: 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>
  );
}

sizin durumunuz olarak, ben böyle yazmanızı öneririz:

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

Lütfen Anahtarın çok önemli olduğuna dikkat edin, çünkü React dizideki verileri farklılaştırmak için Key'i kullanır.


9

Gibi kullanıyorum

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


8

Harika bir soru.

Belli sayıda bileşen eklemek istediğimde yaptığım yardımcı fonksiyon kullanmak.

JSX döndüren bir işlev tanımlayın:

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

//... in JSX

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

8

Kendini çağıran bir işlevi de kullanabilirsiniz:

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

           })()}
        </tbody>

Oluşturma içinde anonim işlevlerin kullanılması, tepkilerde iyi bir uygulama olarak değerlendirilmez, çünkü bu işlevlerin her yeniden oluşturma işleminde yeniden oluşturulması veya atılması gerekir.
Vlatko Vlahek

@VlatkoVlahek, her render döngüsünün yeniden yaratıldığı ve büyük ölçekte performansın düşmesine neden olabilecek işlev sahneleriyle yanlış anlıyorsunuz . Başka bir yerde anonim işlev oluşturmak, performansı önemli bir şekilde etkilemez.
Emile Bergeron

1
@EmileBergeron Bu bir süre önceydi haha. Bu bir pervane olarak kullanılmıyorsa, hiçbir fark olmadığını kabul ediyorum.
Vlatko Vlahek
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.