Frage Schleife innerhalb React JSX


Ich versuche in React JSX (wobei ObjectRow eine separate Komponente ist) Folgendes zu tun:

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

Ich verstehe und verstehe, warum das JSX nicht gültig ist, da JSX Funktionsaufrufen zuordnet. Da ich jedoch aus einem Template-Land komme und für JSX neu bin, bin ich mir nicht sicher, wie ich das oben genannte erreichen würde (indem ich eine Komponente mehrfach hinzufüge).


736
2018-04-05 05:29


Ursprung


Antworten:


Denken Sie daran, als würden Sie nur JavaScript-Funktionen aufrufen. Sie können nicht ein for Schleife innerhalb eines Funktionsaufrufs:

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

Aber Sie können ein Array erstellen und es dann übergeben:

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

Sie können grundsätzlich dieselbe Struktur verwenden, wenn Sie mit JSX arbeiten:

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

Übrigens ist mein JavaScript-Beispiel fast genau das, was das Beispiel von JSX darstellt. Spielen Sie mit Babel REPL um ein Gefühl dafür zu bekommen, wie JSX funktioniert.


754
2018-04-05 05:39



Nicht sicher, ob das für Ihre Situation funktioniert, aber oft Karte ist eine gute Antwort.

Wenn das Ihr Code mit der for-Schleife wäre:

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

Du könntest es so mit schreiben Karte:

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

ES6-Syntax:

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

639
2018-04-05 05:46



Wenn Sie noch kein Array haben map() wie @ FakeRainBrigand die Antwort, und möchte dies inline, so dass die Source-Layout entspricht der Ausgabe näher als @ SophieAlpert die Antwort:

Mit ES2015 (ES6) -Syntax (Spread- und Pfeilfunktionen)

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

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

Re: mit Babel transponieren Vorbehaltsseite sagt, dass Array.from ist für die Verbreitung erforderlich, aber derzeit (v5.8.23) das scheint nicht der Fall zu sein, wenn man ein tatsächliches verbreitet Array. Ich habe ein Dokumentationsproblem offen, um das zu klären. Aber verwenden Sie auf eigene Gefahr oder Polyfill.

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

Kombination von Techniken aus anderen Antworten

Behalten Sie das Quellenlayout für den Ausgang bei, aber machen Sie den Inline-Teil kompakter:

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

Mit ES2015 Syntax & Array Methoden

Mit Array.prototype.fill Sie können dies als Alternative zur Verwendung von Spread wie oben dargestellt tun:

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

(Ich denke, Sie könnten tatsächlich jede Argumentation weglassen fill(), aber ich bin nicht 100%.) Danke an @FakeRainBrigand für die Korrektur meines Fehlers in einer früheren Version des fill() Lösung (siehe Revisionen).

key

In allen Fällen key Attr mildert eine Warnung mit dem Development Build, ist aber im Child nicht erreichbar. Sie können ein zusätzliches Attr übergeben, wenn Sie möchten, dass der Index im Kind verfügbar ist. Sehen Listen und Schlüssel zur Diskussion.


317
2018-04-14 14:08



Einfach verwenden Karte  Array Methode mit ES6-Syntax:

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

Vergiss nicht das key Eigentum.


52
2017-10-30 04:35



Verwenden Array-Karte Funktion ist eine sehr häufige Art und Weise, eine Schleife zu durchlaufen Array von Elementen und erstellen Komponenten nach ihnen in ReagierenDies ist eine großartige Möglichkeit, eine Schleife zu erstellen, die eine ziemlich effiziente und ordentliche Art ist, Ihre Loops zu bearbeiten JSX, Es ist nicht der einzige Weg, es zu tun, aber die bevorzugter Weg. 

Vergessen Sie auch nicht, a einzigartiger Schlüssel für jede Iteration nach Bedarf. Die Map-Funktion erstellt einen eindeutigen Index von 0, aber es wird nicht empfohlen, den Index zu verwenden. Wenn Ihr Wert jedoch eindeutig ist oder wenn ein eindeutiger Schlüssel vorhanden ist, können Sie sie verwenden:

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

Auch ein paar Zeilen von MDN wenn Sie mit der Kartenfunktion auf Array nicht vertraut sind:

map ruft eine bereitgestellte Callback-Funktion einmal für jedes Element in einem auf   Array, in Reihenfolge, und erstellt ein neues Array aus den Ergebnissen. Rückrufen   wird nur für Indizes des Arrays aufgerufen, denen Werte zugewiesen sind,   einschließlich undefined. Es ist nicht für fehlende Elemente der   Array (dh Indizes, die nie gesetzt wurden, die   gelöscht oder denen noch nie ein Wert zugewiesen wurde).

Callback wird mit drei Argumenten aufgerufen: der Wert des Elements,   der Index des Elements und das Array-Objekt, das durchlaufen wird.

Wenn ein thisArg-Parameter zum Zuordnen bereitgestellt wird, wird er als verwendet   Rückruf ist dieser Wert. Andernfalls wird der Wert undefined als verwendet   es ist dieser Wert. Dieser Wert, der letztendlich durch den Rückruf zu beobachten ist, ist   bestimmt nach den üblichen Regeln für die Bestimmung der gesehen   durch eine Funktion.

map mutiert nicht das Array, auf dem es aufgerufen wird (obwohl   Callback, falls aufgerufen, kann dies tun).


41
2018-05-16 13:37



Wenn Sie bereits lodash verwenden, _.times Funktion ist praktisch.

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

33
2017-10-05 05:35



Sie können auch außerhalb des Rückgabeblocks extrahieren:

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

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

25
2018-01-04 05:53