Wie rendere ich Geschwisterelemente, ohne sie in ein übergeordnetes Tag einzuschließen?

81

In den meisten Fällen ist ein übergeordnetes Tag kein Problem.

React.createClass({
    render: function() {
        return (
            <tbody>
                <tr><td>Item 1</td></tr>
                <tr><td>Item 2</td></tr>
            </tbody>
        );
    }
});

In einigen Fällen ist es jedoch sinnvoll, Geschwisterelemente in einer Renderfunktion ohne übergeordnetes Element zu haben, und insbesondere im Fall einer Tabelle möchten Sie keine Tabellenzeile in a umbrechen div.

React.createClass({
    render: function() {
        return (
            <tr><td>Item 1</td></tr>
            <tr><td>Item 2</td></tr>
        );
    }
});

Das zweite Beispiel gibt den folgenden Fehler : Adjacent XJS elements must be wrapped in an enclosing tag while parsing file.

Wie kann ich zwei Geschwisterelemente rendern, ohne sie in ein <div>oder ähnliches zu verpacken ?

Thealexbaron
quelle
3
Ich habe immer Probleme, diese Frage / Antwort zu finden, also habe ich beschlossen, sie selbst zu stellen / zu beantworten. Zusätzliche Erklärungen / Antworten sind willkommen.
Thealexbaron
Ein weiteres Beispiel sind Navigationselemente
Tjorriemorrie

Antworten:

66

Dies ist derzeit eine Einschränkung, wird aber wahrscheinlich zu einem späteren Zeitpunkt behoben ( es gibt einige offene Probleme beim Github-Repo ).

Im Moment können Sie eine Funktion verwenden, die ein Array zurückgibt (dies ist im Grunde eine zustandslose Komponente):

function things(arg, onWhatever){
    return [
        <tr><td>Item 1</td></tr>,
        <tr><td>Item 2</td></tr>
    ];
}

Und verwenden Sie das in Ihrer Komponente.

return (
    <table><tbody>
      {things(arg1, this.handleWhatever)}
      {things(arg2, this.handleWhatever)}
    </tbody></table>
);

Aktualisieren

In React 16 können Sie ein Array aus dem Rendering zurückgeben.

Ein weiteres Update

Sie können jetzt entweder ein Array der obersten Ebene zurückgeben oder verwenden <React.Fragment>.

Bei einem Array müssen wir jedem Element einen Schlüssel zuordnen, da React nicht weiß, dass die beiden Elemente konstant sind, anstatt einer dynamisch erstellten Liste:

function RowPair() {
  return [
    <tr key="first"><td>First</td></tr>,
    <tr key="second"><td>Second</td></tr>,
  ]
}

Mit React.Fragmentverhält es sich viel mehr so, als würde man es in ein <div>oder ähnliches einwickeln , wobei a keynicht erforderlich ist, wenn wir die Kinder nicht dynamisch erstellen. Zuerst können wir das Array in ein Fragment einschließen:

function RowPair() {
  return <React.Fragment>{[
    <tr key="first"><td>First</td></tr>,
    <tr key="second"><td>Second</td></tr>,
  ]}</React.Fragment>
}

Und dann können wir das Array und keys vollständig entfernen:

function RowPair() {
  return <React.Fragment>
    <tr><td>First</td></tr>
    <tr><td>Second</td></tr>
  </React.Fragment>
}
Räuber
quelle
2
Warum sagen alle, dass das funktioniert? Nicht erfasster Fehler: x.render (): Ein gültiges React-Element (oder null) muss zurückgegeben werden. Möglicherweise haben Sie undefiniert, ein Array oder ein anderes ungültiges Objekt zurückgegeben.
Xogle
@Xogle In der React-API muss sich etwas geändert haben. Scheint nicht mehr zu funktionieren.
Petr Peller
1
@ FakeRainBrigand Ich sehe das Problem. Es ist keine "zustandslose Komponente", sondern eine Funktion, die ein Array zurückgibt. Zustandslose Komponenten können keine Arrays zurückgeben und Sie können keine einfache Funktion mit dem Redux-Speicher verbinden.
Petr Peller
@PetrPeller benutzt du jsx? Im Beispiel rufe ich es wie eine Funktion auf.
Brigand
Ich verstehe nicht alle positiven Stimmen - das beantwortet die Frage überhaupt nicht. Die Frage ist, wie Geschwisterelemente ohne übergeordnetes Element gerendert werden können, und diese Antwort rendert immer noch ein übergeordnetes Element.
Dancrumb
33

Ich weiß, dass dies ein alter Beitrag war, aber vielleicht könnte meine Antwort eine Hilfe für Neulinge wie mich sein.

In Reaktion 16.2 wurde eine verbesserte Unterstützung für Fragmente hinzugefügt.

Sie können es jetzt folgendermaßen zurückgeben:

return (
  <>
    <tr><td>Item 1</td></tr>
    <tr><td>Item 2</td></tr>
  </>
);

Sie können es mit <></>oder einwickeln <Fragment></Fragment>.

Wenn Sie einige Attribute übergeben möchten, wird zum Zeitpunkt des Schreibens nur der Schlüssel unterstützt, den Sie verwenden müssen, <Fragment />da die kurze Syntax <></>keine Attribute akzeptiert.

Hinweis: Wenn Sie die kurze Syntax verwenden möchten, stellen Sie sicher, dass Sie Babel 7 verwenden .

Quellenreferenz

Onoya
quelle
1
Genau das, wonach ich gesucht habe, danke! Nur für den Fall, dass es jemand anderes benötigt: Importieren Sie React, {Fragment} aus 'react'
Chris
Ich kann die Implementierung Fragmentin ihrem Repository nicht finden. Kann mir bitte jemand etwas zeigen? Danke :)
Ramon Balthazar
Ich kann es nicht zum Laufen bringen, selbst wenn ich Babel-cli installiere ... auch nur für die <> Lösung. Wie ist es möglich @onoya Ich werde bald einen Thread veröffentlichen,
Gaelle
2

Ein übergeordnetes Element ist in den meisten Fällen hilfreich, da Sie beispielsweise einen übergeordneten Klassennamen haben können, der auf den Stil untergeordneter Elemente und einige andere Szenarien abzielt ...

Aber wenn Sie das wirklich nicht wollen, können Sie verwenden React.Fragment

Also mach einfach so etwas:

<React.Fragment>
  <First />
  <Second />
  <Third />
</React.Fragment>

Ab Version 16.2 wird auch eine verkürzte Version verwendet <>, die in der Renderfunktion folgendermaßen aussieht:

render() {
  return (
    <>
      <First />
      <Second />
      <Third />
    </>
  );
}

Wenn Sie Version 16.0 und höher verwenden, können Sie auch ein Array von Elementen zurückgeben, für die kein übergeordneter Wrapper erforderlich ist.

render() {
 return [
  <h1 key="heading">Hello from Alireza!</h1>,
  <p key="first">Here where I'm!</p>,
  <p key="second">And again here :)</p>
 ];
}
Alireza
quelle
0

Sie können es wie folgt in die Klammern einwickeln:

React.createClass({
    render: function() {
        return (
          [
            <tr><td>Item 1</td></tr>
            <tr><td>Item 2</td></tr>
          ]
        );
    }
});
Vitaliy Andrusishyn
quelle
Wie wäre es, wenn Sie auch Object.keys()innerhalb der Rücksendung verwenden müssen?
Juha Untinen
Z.B. return ( [ <tr><td>Header</td></tr>{ Object.keys(this.props.data).map(function(item) { <tr><td>{data}</td></tr> }) } ] ); Mit 15.4.2 gibt es Unexpected token, expected ,in der Eröffnungsklammer innerhalb der Rückkehr
Juha Untinen
Versuchen Sie Folgendes: return ({Object.keys (this.props.data) .map (Funktion (Element) {<tr> <td>{data}</td> </ tr>}). unshift ({< tr> <td> Header </ td> </ tr>})});
Vitaliy Andrusishyn
Dies funktioniert nicht, muss noch ein Komma zwischen <tr> -s haben
Philipp Munin
0

Dieses Beispiel funktioniert gut für mich:

let values = [];

if (props.Values){
  values = [
    <tr key={1}>
      <td>props.Values[0].SomeValue</td>
    </tr>
  ,
    <tr key={2}>
        <td>props.Values[1].SomeValue</td>
        </tr>
    ];
}

return (
    <table className="no-border-table table">
      <tbody>
        <tr>
            <th>Some text</th>
        </tr>
        {values}
      </tbody>
    </table>
)
MrDuDuDu
quelle
0

So etwas hat bei mir funktioniert

this.props.map((data,index)=>{return( [ <tr>....</tr>,<tr>....</tr>];)});
Superve
quelle
-2

Für diejenigen, die TypeScript verwenden, lautet die korrekte Syntax:

return [
  (
    <div>Foo</div>
  ),
  (
    <div>Bar</div>
  )
];
0leg
quelle
1
Dies ist identisch mit der Antwort von @thealexbaron und es hat nichts mit TypeScript zu tun
andrewarchi