Array.map()
, Array.filter()
oder Array.find()
schöne deklarative Methoden, die wir als Ausdrücke in JSX innerhalb von geschweiften Klammern {}
nutzen können.Array.map()
kann bspw. modifizierte Items zurückgeben, die selbst wiederum JSX beinhalten. Das ist insofern praktisch, als es uns weitere Flexibilität verschafft und es uns ermöglicht, Datensammlungen in React-Elemente zu verwandeln.key
-Prop. Diese dient dazu, dem Reconciler (also dem React-Vergleichsalgorithmus) eine Möglichkeit zu geben, um Listen-Elemente zu identifizieren und letztendlich vergleichen zu können. Der Reconciler erkennt dadurch, welche Array-Elemente hinzugefügt, entfernt oder modifiziert wurden. Die key
-Prop nimmt dabei die Funktion einer eindeutigen ID ein und muss innerhalb dieses Arrays einmalig sein. In der Praxis wird hier typischerweise die ID eines Datensatzes verwendet.map()
-Methode zurückgegeben wird, würde also korrekt so aussehen:CryptoList
-Komponente mit denselben Keys an anderer Stelle, auch in der gleichen Komponente, problemlos noch ein zweites Mal verwenden könnten. Nur eben nicht innerhalb dieses einen Loops.key
-Prop immer direkt in der von der Iterator-Funktion zurückgegebenen Toplevel-Komponente oder dem Array-Element vorhanden sein muss, nicht in der von dieser Komponente zurückgegebenen JSX.CryptoListItem
-Komponente:key
-Prop, die wir zuvor hinzugefügt haben ist nun nicht mehr da. Unser map()
-Aufruf würde sich dafür wie folgt verändern:<li></li>
-Element ist, welches letztendlich gerendert wird, muss dennoch die <CryptoListItem />
-Komponente die key
-Prop bekommen, da sie es ist, die von Array.map()
an der entsprechenden Stelle im JSX zurückgegeben wird.CryptoList
-Komponente könnte durch Verwendung der Object-Spread Syntax weiter vereinfacht werden:currency
-Objekts entsprechend als gleichnamige Props an die CryptoListItem
-Komponente übertragen.Array.map()
sähe das analog dazu so aus:render()
-Methode immer nur ein Element auf oberster Ebene zurückgeben darf. Also etwa:render()
-Methode direkt und ohne umschließendes Eltern-Element mehrere li
-Elemente zurück, was zu einer Fehlermeldung führt. Manchmal ist dies aber notwendig, bspw. wenn sich das umschließende Element in einer Eltern-Komponente befinden, die Kind-Elemente aber durch eine eigene Komponente erzeugt werden soll.table
, ul
, ol
, dl
, …) ist es aber nicht erlaubt, bspw. ein div
-Element als Zwischenebene zu verwenden, um die Regel zu erfüllen stets nur ein einzelnes Root-Element aus einer Komponente zurückzugeben. In diesem Fall kommt das Fragment ins Spiel und würde angewendet auf das obige Beispiel folgende Änderung bedeuten, um valides JSX zu erzeugen:key
-Prop besitzen muss. Mit der Fragment
-Komponente ist dies möglich. Schauen wir uns ein weiteres, etwas umfassenderes und praxisnäheres Beispiel an:div
oder span
oder ein sonstiges Element um <dt><dt>
und <dd></dd>
zu wrappen. Dies würde zu folgender Ausgabe führen:dl
-Element nur dt
und dd
als Kind-Element erlaubt. Das Fragment hilft uns hier also gültiges JSX zu erzeugen, ohne dabei gleichzeitig das HTML ungültig werden zu lassen. Dies war in React bis zur Einführung von Fragments in Version 16.3. ein Problem und führte dazu, dass Komponenten unnötig kompliziert implementiert werden mussten, um weder gegen JSX- noch gegen HTML-Regeln zu verstoßen.<Fragment>
geschrieben werden statt <React.Fragment>
. Dies kann, insbesondere wenn viele Fragment
-Elemente verwendet werden noch etwas Schreibarbeit sparen.Fragment
keine Props besitzen kann, alle Elemente, die in einer Schleife verwendet werden jedoch eben eine key
-Prop besitzen müssen. In diesem Fall muss dann doch wieder auf <React.Fragment>
zurückgegriffen werden.render()
-Funktion von Komponenten, also sowohl von Class Components als auch Stateless Functional Components kann grundsätzlich ein React-Element (natürlich auch in Form von JSX), einen String, eine Nummer, null
(für den Fall, dass nichts gerendert werden soll) oder ein Array aus den zuvor genannten Typen zurückgeben.render()
-Methoden in den Komponenten übersichtlich zu halten. Diese Möglichkeiten werde ich euch hier vorstellen.if
/else
-Konstrukt.NotificationList
, die eine Liste an Items in Form einer Prop entgegen nimmt. Enthält diese Liste Einträge, werden diese als simple ungeordnete Liste ausgegeben. Ist die Liste hingegen leer, lassen wir unsere Komponente stattdessen eben den Hinweis ausgeben, dass keine neuen Benachrichtigungen vorhanden sind.edit
und view
. Je nachdem, ob wir uns im View-Mode oder im Edit-Mode befinden, möchten wir nur den Text anzeigen oder ein vorausgefülltes Textfeld mit dem jeweiligen letzten aktuellen Wert.render()
-Methode der Komponente ab. Wir prüfen hier auf den Wert der State-Eigenschaft mode
: Ist dieser edit
, geben wir direkt das Eingabefeld zurück („early return“). Ist dieser nicht edit
, gehen wir davon aus, dass der „Standardfall“ eintritt, der in diesem Falle der Ansichtsmodus (view
) wäre. Der else
-Teil der Condition ist hier also gar nicht nötig und würde lediglich unnötig Komplexität hinzufügen. Gerendert wird jeweils der Text, einmal editierbar als value
eines input
-Felds, einmal lediglich als Textknoten und dazu jeweils ein Button, um die State-Eigenschaft mode
der Komponente zwischen view
und edit
hin und her zu wechseln.if
, if
/else
oder if
/else if
/else
-Konstrukte sind in verschiedenen Varianten, auf die ich hier gleich noch eingehen werde, eine häufige Form wenn es darum geht, eine Ausgabe auf Basis von State und Props innerhalb einer Komponente zu erzeugen.null
zurückzugeben ist wohl der einfachste Fall für Conditional Rendering. Gibt die render()
-Methode einer Komponente null
zurück, wird diese nicht gerendert und erscheint daher auch nicht im DOM. Dies kann manchmal sinnvoll sein, bspw. wenn eine Fehler-Komponente nur dann angezeigt werden soll, wenn auch ein Fehler aufgetreten ist.null
zurückgegeben und somit auch nichts gerendert. Existiert die Eigenschaft hingegen, wird die entsprechende Fehlermeldung in einem div
ausgegeben, wozu wir wieder auf das Conditional Rendering mit einem einfachen if
zurückgreifen.Bedingung ? Erfüllt : Nicht Erfüllt
. Also etwa: isLoggedIn ? 'Logout' : 'Login';
isLoggedIn
-Prop entweder die Beschriftung Logout oder Login.is-disabled
gekennzeichnet, aktive Benutzer hingegen mit einer Klasse is-active
.de
) ist. In allen anderen Fällen zeigen wir dem Benutzer nur ein Textfeld an, in das dieser sein entsprechendes Bundesland frei eintragen kann. Hier sollte jedoch immer abgewogen werden ob dies sinnvoll ist, denn der Ternary Operator kann insbesondere in komplexerem JSX schnell unübersichtlich werden.&&
) und Logical OR (||
)undefined
und verursacht somit keinerlei sichtbare Ausgabe im User Interface:isMenuVisible
-Prop true
ist und dann eine Menu
-Komponente anzeigen. Ist der Wert false
, gibt der Ausdruck undefined
zurück und die Komponente rendert dementsprechend keine Ausgabe an dieser Stelle.isLoggedIn
Prop true
ist, der Benutzer also eingeloggt ist oder Login, wenn der Benutzer nicht eingeloggt ist.render()
-Methodenrender()
-Methode in eigene renderXY()
-Methoden zu verfrachten. Die render()
-Methode stellt so gesehen den Kern einer Komponente dar, ist sie doch dafür verantwortlich zu entscheiden, was ein Benutzer später auf seinem Bildschirm sieht. Sie sollte also nicht zu komplex werden, nicht unnötig viel Logik enthalten und lesbar sein.render()
-Methoden in kleine, übersichtliche Häppchen zu unterteilen und als eigene Klassenmethoden zu implementieren. Dies führt bei sinnvoller Benennung der jeweiligen Methoden meist zur Erhöhung und zu besserer Verständlichkeit des Codes. Meist werden die einzelnen render()
-Methoden noch mit if
-Blöcken kombiniert:render()
-Methode erhöhen, führt aber unweigerlich auch dazu, dass sich die Komplexität einer Komponente (in etwas geringerem Maß) erhöht. Viele Leute – ich zähle mich dazu – raten daher eher dazu, Teile des Codes wiederum in eigene gekapselte Function Components auszulagern statt renderXY()
-Methoden zu verwenden.render()
-Methode innerhalb einer Komponente zu implementieren sollte darüber nachgedacht werden, stattdessen eine eigene, separate Function Component zu erstellen.render()
-Methoden innerhalb einer Komponente können wie eben bereits angesprochen auch eigene, neue, bevorzugterweise Function Components erstellt werden. Diese bekommen dann entsprechende Props aus ihrer Eltern-Komponente hereingereicht und kümmern sich dann als eigenständige, unabhängige, wiederverwendbare und testbare Komponente um die Anzeige der ihnen übergebenen Daten.render()
-Methode eben zu groß und unübersichtlich wird.type
-Attribute. Zum Label gehört außerdem auch eine id, die ebenfalls für jedes Feld angegeben werden muss:TextField
-Komponente und lagern das sich wiederholende JSX aus unserer Formular-Komponente dorthin aus:id
, die wir benötigen, um das Label mit dem Eingabefeld zu verknüpfen und ein Label als solches. Mittels Object Rest/Spread fügen wir dem input
-Element dann außerdem alle weiteren Props, die der Komponente übergeben werden, als Attribut hinzu.render()
-Methode gemacht, die auf oberster Ebene aus wenigen Komponenten besteht. Möchten wir in Zukunft außerdem eine Änderung vornehmen, die sich auf alle Textfelder auswirkt, bspw. eine neue Klasse hinzufügen, muss dies nur noch an einer einzigen Stelle geändert werden – in der neuen TextField
-Komponente.