Wie kann JSX in einer anderen return-Anweisung in React mehrere Zeilen zurückgeben?

99

Einzelne Zeile funktioniert gut

render: function () {
  return (
    {[1,2,3].map(function (n) {
      return <p>{n}</p>
    }}
  );
}

nicht für mehrere Zeilen

render: function () {
  return (
    {[1,2,3].map(function (n) {
      return (
        <h3>Item {n}</h3>
        <p>Description {n}</p>
      )
    }}
  );
}

Vielen Dank.

Shawn
quelle
1
Für weitere Informationen zu diesem speziellen Thema: github.com/facebook/react/issues/2127
plus-
nicht return ("asdf" "asdf");du willstreturn ["asdf", "asdf"];
neaumusic

Antworten:

149

Versuchen Sie, sich die Tags als Funktionsaufrufe vorzustellen (siehe Dokumente ). Dann wird der erste:

{[1,2,3].map(function (n) {
  return React.DOM.p(...);
})}

Und der zweite:

{[1,2,3].map(function (n) {
  return (
    React.DOM.h3(...)
    React.DOM.p(...)
  )
})}

Es sollte jetzt klar sein, dass das zweite Snippet nicht wirklich Sinn macht (Sie können in JS nicht mehr als einen Wert zurückgeben). Sie müssen es entweder in ein anderes Element einschließen (höchstwahrscheinlich das, was Sie möchten, auf diese Weise können Sie auch eine gültige keyEigenschaft bereitstellen ), oder Sie können Folgendes verwenden:

{[1,2,3].map(function (n) {
  return ([
    React.DOM.h3(...),
    React.DOM.p(...)
  ]);
})}

Mit JSX-Zucker:

{[1,2,3].map(function (n) {
  return ([
    <h3></h3>, // note the comma
    <p></p>
  ]);
})}

Sie müssen das resultierende Array nicht reduzieren, React erledigt das für Sie. Siehe die folgende Geige http://jsfiddle.net/mEB2V/1/ . Nochmals: Das Einwickeln der beiden Elemente in einen Div / Abschnitt ist auf lange Sicht höchstwahrscheinlich besser.

Jan Olaf Krems
quelle
4
Ja, tatsächlich klar dokumentiert facebook.github.io/react/tips/…
Shawn
1
Die Verwendung von return ([...]) ohne das Abflachungsbit gibt mir das Markup genau so, wie ich es wollte, obwohl das zurückgegebene Array nicht abgeflacht sein muss, aber in meinem speziellen Fall hat es keinen Einfluss auf die endgültige Ausgabe. Oder ist es?
Shawn
Vielen Dank! BIS! Aktualisieren meiner Antwort, um einen Link zu einer JSFiddle aufzunehmen, der zeigt, dass das Reduzieren optional ist. Enthält auch den Link zu den React-Dokumenten.
Jan Olaf Krems
13
Dies funktioniert nicht mehr (ab 0.9ish)Uncaught Error: Invariant Violation: Product.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.
dogmatisch69
2
@ TimFletcher Es ist in Ordnung, ein Array als Teil des Renderns einer Komponente zurückzugeben, z <div>{ this.props.foos.map(function() { return <Foo /> }) }</div>. Die renderFunktion der Komponente kann dieses Array jedoch nicht zurückgeben, ohne es zu verpacken, z. B. in ein div.
Henrik N
35

Es scheint, dass die alte Antwort über die Rückgabe eines Arrays nicht mehr gilt (möglicherweise seit React ~ 0.9, wie @ dogmatic69 in einem Kommentar schrieb ).

In den Dokumenten wird angegeben, dass Sie einen einzelnen Knoten zurückgeben müssen:

Maximale Anzahl von JSX-Stammknoten

Derzeit können Sie beim Rendern einer Komponente nur einen Knoten zurückgeben. Wenn Sie beispielsweise eine Liste der zurückzugebenden Divs haben, müssen Sie Ihre Komponenten in ein Div, einen Span oder eine andere Komponente einschließen.

Vergessen Sie nicht, dass JSX zu regulärem JS kompiliert wird. Die Rückgabe von zwei Funktionen ist syntaktisch nicht wirklich sinnvoll. Setzen Sie auch nicht mehr als ein Kind in ein Ternär ein.

In vielen Fällen können Sie Dinge einfach in a <div>oder a einwickeln <span>.

In meinem Fall wollte ich mehrere <tr>s zurückgeben. Ich habe sie in einen <tbody>Tisch gewickelt - ein Tisch darf mehrere Körper haben.

BEARBEITEN: Ab React 16.0 ist das Zurückgeben eines Arrays anscheinend wieder zulässig, sofern jedes Element Folgendes enthältkey : https://facebook.github.io/react/blog/2017/09/26/react-v16.0.html # new-render-return-types-fragmente und -strings

BEARBEITEN: Mit React 16.2 können Sie eine Liste von Elementen mit <Fragment>…</Fragment>oder sogar umgeben <>…</>, wenn Sie dies einem Array vorziehen: https://blog.jmes.tech/react-fragment-and-semantic-html/

Henrik N.
quelle
3
Was können Sie tun, wenn Sie mehrere zurückgeben möchten <li>? Vorausgesetzt, ich kann nicht einfach alles <ul>
einpacken
@Banjocat Ich fürchte, ich weiß nicht: / Du darfst Listen verschachteln , also könntest du so etwas zurückgeben, <li><ul><li>one</li><li>two</li></ul></li>wenn das in deiner Situation funktioniert. Oder: Ein Wrapping-Div wäre nicht unbedingt gültig, aber vielleicht wird es in allen relevanten Browsern gut dargestellt? Wenn Sie es versuchen, lassen Sie es uns wissen.
Henrik N
1
@ Banjocat ... Ich würde gerne eine bessere Antwort auf Ihre Frage wissen. Vielleicht sollten Sie es als normale Stackoverflow-Frage stellen und sehen, ob Sie eine andere Antwort erhalten.
user1175849
@ user1175849 Vielleicht könnten Sie diese Frage dann posten :)
Henrik N
1
@HenrikN Fwiw, eine "Teilmenge" von liin ein spanoder einwickeln divfunktionierte nicht gut für mich. Der Div hat das Rendering ernsthaft unterbrochen, und zumindest in meinem Anwendungsfall hat die Spanne das CSS durcheinander gebracht. 2 ¢: Der Versuch, mehrere Teilmengen von lis zurückzugeben, ist ein Codegeruch. Wir haben ein ulals eine Art Pulldown-Menü verwendet, und ich wollte zunächst, dass viele Komponenten "Abschnitte" von lis zurückgeben. Am Ende war es besser, den gesamten Menücode in eine einzelne Komponente zu "verankern", ulals lis aus mehreren Quellen einzuschleusen . Ich denke, es hat auch das mentale Modell für die Benutzeroberfläche ein wenig sauberer gemacht.
Ruffin
13

Ab React v16.0.0 können mehrere Elemente zurückgegeben werden, indem sie in eine eingeschlossen werdenArray

render() {
  return (
    {[1,2,3].map(function (n) {
      return [
        <h3>Item {n}</h3>.
        <p>Description {n}</p>
      ]
    }}
  );
}

Ebenfalls ab React v16.2.0 wird eine neue Funktion namens aufgerufen, React Fragmentsmit der Sie mehrere Elemente umschließen können

render() {
  return (
    {[1,2,3].map(function (n, index) {
      return (
        <React.Fragment key={index}>
            <h3>Item {n}</h3>
            <p>Description {n}</p>
        </React.Fragment>
      )
    }}
  );
}

Gemäß Dokumentation:

Ein häufiges Muster in React ist, dass eine Komponente mehrere Elemente zurückgibt. Mit Fragmenten können Sie eine Liste von untergeordneten Elementen gruppieren, ohne dem DOM zusätzliche Knoten hinzuzufügen.

Mit der expliziten Syntax deklarierte Fragmente können Schlüssel haben. Ein Anwendungsfall hierfür ist das Zuordnen einer Sammlung zu einem Array von Fragmenten, um beispielsweise eine Beschreibungsliste zu erstellen:

function Glossary(props) {
  return (
    <dl>
      {props.items.map(item => (
        // Without the `key`, React will fire a key warning
        <React.Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </React.Fragment>
      ))}
    </dl>
  );
}

Schlüssel ist das einzige Attribut, das an Fragment übergeben werden kann. In Zukunft werden wir möglicherweise zusätzliche Attribute unterstützen, z. B. Ereignishandler.

Shubham Khatri
quelle
7

Möglicherweise möchten Sie auch mehrere Listenelemente in einer Hilfsfunktion innerhalb einer React-Komponente zurückgeben. Geben Sie einfach ein Array von HTML-Knoten mit dem keyAttribut zurück:

import React, { Component } from 'react'

class YourComponent extends Component {
  // ...

  render() {
    return (
      <ul>
        {this.renderListItems()}
      </ul>
    )
  }      

  renderListItems() {
    return [
      <li key={1}><a href="#">Link1</a></li>,
      <li key={2}><a href="#">Link2</a></li>,
      <li key={3} className="active">Active item</li>,
    ]
  }
}
Dmitriy
quelle
2

Sie können createFragmenthier verwenden.

https://facebook.github.io/react/docs/create-fragment.html

import createFragment from 'react-addons-create-fragment';
...
{[1,2,3].map((n) => createFragment({
    h: <h3>...</h3>,
    p: <p>...</p>
  })
)}

(hier mit ES6- und JSX-Syntax)

Sie müssen zuerst das react-addons-create-fragmentPaket hinzufügen :

npm install --save react-addons-create-fragment

Vorteil gegenüber Jan Olaf Krems 'Lösung: Reagieren beschwert sich nicht über das Fehlen key

Sylvain
quelle
Korrigieren Sie mich, wenn ich falsch liege, aber Sie können die Schlüssel einfach manuell hinzufügen. am Beispiel von Jan: Das erste Array-Element erhält zB <h3 key = {i}> </ h3> und das zweite Array-Element etwas anderes wie <p> key = {i + '-foo'}> </ p>
Nerdess
1

Aktualisiert

Verwenden Sie React Fragment. Es ist einfach. Link zur Fragmentdokumentation.

render() {
  return (
    <>
    {[1,2,3].map((value) => <div>{value}</div>)}
    </>
  );
}

Alte Antwort - veraltet

Mit React> 16 können Sie React -Composite verwenden .

import { Composite } from 'react-composite';

// ...

{[1,2,3].map((n) => (
  <Composite>
    <h2>Title {n}</h2>
    <p>Description {n}</p>
  </Composite>
))};

Natürlich muss React-Composite installiert werden.

npm install react-composite --save
Herr Br
quelle
0

Es ist einfach durch React Fragment <></>und React.Fragment:

return (
    <>
      {[1, 2, 3].map(
        (n, index): ReactElement => (
          <React.Fragment key={index}>
            <h3>Item {n}</h3>
            <p>Description {n}</p>
          </React.Fragment>
        ),
      )}
    </>
  );
Masih Jahangiri
quelle