16. Mär 2021
Lesedauer 28 Min.
Einbinden von React
Cross-Plattform-Development mit Webtechnologien (Teil 4)
Ionic bindet für die Cross-Plattform-Entwicklung auf Open-Source-Basis die populäre User-Interface-Bibliothek React ein.

Seit Version 4 unterstützt Ionic neben der Angular-Plattform für die Entwicklung alternativ auch React als Framework. Mit Ionic-React lassen sich auf einer zentralen Code-Basis portable Anwendungen für das Web, die mobile Welt und den klassischen Desktop programmieren. Bei Ionic-React handelt es sich um eine für React optimierte und mit dem React-Framework vollständig-kompatible Version von Ionic. Das Ionic-Produkt enthält mehr als 100 für React fertig einsetzbare Komponenten, derzeit vorwiegend zur Gestaltung der Benutzeroberfläche. Achtung: Das Ionic-Produkt darf nicht mit dem Open-Source-Projekt React-Ionic verwechselt werden, welches nicht von Ionic stammt und vermutlich von deren Entwicklern eingestellt wird.Ionic-React findet zunehmend Verbreitung in der Entwicklungsgemeinde von React: Inzwischen liefert unter anderem FusionCharts (ein Unternehmen der bekannten Idera-Gruppe) eine auf Ionic-React optimierte Version ihrer Software-Komponenten aus. Mit FusionCharts bindet man interaktive Diagramme und Grafiken in eine Anwendung ein. Zur Visualisierung von Daten stehen in FusionCharts höherwertige Komponenten (Diagramme, geographische Karten, Widgets und Dashboards (Anzeige- oder Instrumententafeln)) alle auf Basis von Ionic-React zur Verfügung. Die Realisierung in einem Ionic-React-Projekt erfolgt mit dem npm-Package fusioncharts und einem weiteren JavaScript-Modul react-fusioncharts.Facebook stellte React bereits im Jahr 2013 als Open-Source-Lösung für die Entwicklung von Web-Apps zur freien Verfügung. Nach der Übernahme von Instagram realisierte Facebook den Online-Dienst neu auf der Basis von React. Den Kern von React bilden Komponenten mit denen man eine Anwendung analog dem Prinzip von Legosteinen aus einem Baukasten zusammensetzt. Ob ausschließlich mit React entwickelte Komponenten den sich abzeichnenden Standard für Webkomponenten erfüllen, wird die Zukunft zeigen.
npm-konformes Anlegen eines React-Projekts
Der Nodes-Package-Manager (npm) dient in der JavaScript-Welt als Werkzeug für die Anlage von Entwicklungsprojekten. Über npm init erzeugt man für jedes Entwicklungsprojekt die zentrale package.json-Datei – diese definiert die benötigten Ressourcen (Anwendungen, Moduln, Packages et cetera), eingesetzten Entwicklungswerkzeuge und vorhandene Abhängigkeiten innerhalb eines Projekts. Der Befehl npm init <initializer> generiert anhand vorhandener Definitionen über das npm-Package create-<initializer> ein neues Entwicklungsprojekt mit allen benötigten Dateien, Verzeichnissen und Node.js-Module. Ein neues React-Projekt erzeugt der Befehl npm init react-app mein-proj und legt dieses im Ordner mein-proj ab.
React hat schnell eine große Verbreitung gefunden, beispielsweise setzen neben Facebook auch Airbnb, The Wall Street Journal, Netflix und WhatsApp die JavaScript-Bibliothek ein. Airbnb hat sogar einen eigenen Styleguide für das Arbeiten mit React veröffentlicht. Zwischenzeitlich hat PayPal ein eigenes SDK (Software-Development-Kit) mit React-Komponenten für die Integration der PayPal-Services bereitgestellt.Typischerweise entwickelt man mit React eine sogenannte Single-Page-Anwendung (SPAs). Eine SPA besteht aus einem einzigen HTML-Dokument, deren weitere Inhalte dynamisch nachgeladen werden. Normalerweise findet bei einer SPA der Vorgang der Aufbereitung für die Anzeige (Rendern) und das dynamische Nachladen auf dem Client statt. React ermöglicht einem Entwickler jedoch auch ein serverseitiges Rendern und Laden der HTML-Dokumente. Dabei kommt auf der Serverseite Node.js als JavaScript-Engine (siehe Teil 2) zum Einsatz. Innerhalb einer mit React realisierten Web-App besteht Wahlfreiheit: man kann beide Möglichkeiten client- und serverseitiges Rendern inzwischen auch beides zusammen einsetzen.Bei React handelt es sich streng genommen nicht um ein Framework, sondern um eine JavaScript-Library. Das zentrale Konzept von React stellt die Komponente dar. Eine React-Komponente enthält alles Notwendige für die eigene Darstellung. Somit enthält eine React-Komponente neben den Elementen der Benutzeroberfläche auch die zugehörige Darstellungslogik; beides zusammen als Bestandteil in einer Komponente. Die Realisierung einer React-Komponente erfolgt über eine JavaScript-Funktion, die ein spezielles API (Application-Programming-Interface) von React benutzt. Daher argumentieren manche Experten, handelt es sich bei React nicht um eine Library, sondern um ein Framework.

React arbeitet internmit einer eigenen Repräsentation des HTML-DOMs – dem Virtual-DOM – und synchronisiert diesen automatisch mit dem Real-DOM des Webbrowsers(Bild 1)
Simon
Eine spezielle JavaScript-Methode render() des React-APIs fügt alle über Komponenten beschriebene User-Interface-Elemente dem React-DOM hinzu. Dieses React-DOM, auch Virtual-DOM genannt, stellt die Basis dar, um letztendlich die Darstellung über das HTML-DOM im Webbrowser durchzuführen (Bild 1). Den erforderlichen Abgleich des Virtual-DOMs mit den Elementen des HTML-DOMs nimmt React automatisch vor. Deshalb erreicht man mit einer React-App eine einfachere Programmierung und bessere Performance als mit einer herkömmlichen HTML/JavaScript-Anwendung.
Grundkonzepte der User-Interface-Library React
Facebook rückt für die Entwicklung mit React folgende Grundkonzepte ins Zentrum: Wiederverwendung durch Komponentenorientierung, Spracherweiterung für JSX (JavaScript Syntax Extension oder JavaScript XML), Rendern mit dem Virtual-DOM sowie Unidirektionaler Data-Flow (ohne Event-Chaos). Komponenten stellen die zentralen Elemente einer jeden mit React entwickelten Anwendung dar. Die Realisierung einer Komponente erfolgt mittels ECMAScript 2015 (ES6)- oder TypeScript-Klassen, abgeleitet von der Basis-Klasse React.Component.Dabei besteht eine React-Komponente sowohl aus einem User-Interface-Teil als auch aus Logik zur Steuerung des User-Interface. React-Komponenten besitzen einen veränderlichen, internen Zustand (in der React-Terminologie State genannt); sie können von außen über Eigenschaften (Properties) konfiguriert werden. Die mit React verfügbare JavaScript-Spracherweiterung JSX (JavaScript Syntax Extension oder JavaScript XML) vereinfacht das Schreiben von React-Anwendungen erheblich. JSX basiert auf der XML (Extensible Markup Language) – einer Auszeichnungssprache zur Beschreibung hierarchisch strukturierter Daten in Form einer Textdatei.Das CSS-Framework Bootstrap in React-App nutzen
Um Bootstrap für die Gestaltung der HTML-Dokumente in einer React-App zu nutzen, hilft die nachfolgende Anleitung: Zuerst lädt man das ZIP-Archiv der Compiled CSS and JS-Version von Bootstrap herunter: https://getbootstrap.com/docs/4.0/getting-started/download/. Anschließend trägt man in der index.html-Datei der React-App den folgenden Verweis auf die Bootstrap-CSS ein: <link rel="stylesheet" href="css/bootstrap.min.css">. Die index.html-Datei befindet sich im pub-Verzeichnis des Projektordners.
Der Einsatz von JSX in React ist jedoch nicht zwingend erforderlich, da man die gleiche Funktionalität auch direkt mit regulärem JavaScript mittels der React-Methoden realisieren kann. Arbeitet man allerdings als Entwickler mit JSX, so sinkt der Aufwand für die Programmierung, da man wesentlich weniger JavaScript-Code benötigt. Zudem erhält man mittels kompaktem JSX wesentlich schneller einen Überblick zum Quellcode. Dies erleichtert auch die Wartung, da JSX-Quellcode leichter zu lesen ist. Sogar eine Mischung von JSX mit normalen JavaScript wird unterstützt. Die Konvertierung von JSX in gültigen JavaScript-Code übernimmt der Open-Source-Compiler Babel.Beim Rendern einer Komponente arbeitet React zunächst im Memory auf einem virtuellen HTML-DOM – dem Virtual-DOM. Um den kompletten HTML-DOM nicht neu aufbauen zu müssen, vergleicht React den virtuellen DOM mit dem vorherigen, also mit dem derzeit aktiven Virtual-DOM. Anschließend generiert React aus den Unterschieden der beiden virtuellen DOMs eigenständige Operationen, die auf dem HTML-DOM ausgeführt werden, um diesen in den neu beschriebenen Zustand zu überführen. Somit aktualisiert React nur Komponenten, die sich tatsächlich geändert haben; was sich positiv auf die Performance auswirkt.

Der Unidirektionale Data-Flowbietet einen einheitlichen und geregelten Datenfluss zwischen den Komponenten einer Web-App; er bildet die Grundlage für den von Facebook entwickelten Architekturansatz Flux genannt(Bild 2)
Simon
Die Verarbeitung der Interaktionen des Endbenutzers erfolgt wie bei allen HTML/JavaScript-Anwendungen über Events. Die Benutzeroberfläche, auch View genannt, löst Events aus, die den Zustand der Anwendung verändern: Ein in der React-App zugeordneter Event-Handler nimmt eine Änderung des State (Zustand) mittels der Methode setState() vor (Bild 2). Die Änderung des Zustands zusammen mit den aktuellen Datenkonstellationen spiegeln sich in der Benutzeroberfläche (View, render(), JSX) wider. Damit erhält man ein einheitliches Verfahren mit genau definierten Zuständigkeitsbereichen: Unidirektionaler Data-Flow genannt. Dieser reduziert die Komplexität für das ansonsten aufwendige Handling und die Koordination der Daten, Events und Benutzungsschnittstelle erheblich.Für die komponentenorientierte Programmierung mit React benötigt man drei verschiedene JavaScript-Bibliotheken/npm-Packages: Facebook bietet mehrere Möglichkeiten an, um diese drei Bibliotheken der Programmierung zugänglich zu machen. Zum einen stehen diese im Internet zur Auslieferung über UNPKG einem CDN (Content Delivery/Distribution Network) bereit. Dort erhält man die .js-Dateien durch Einbindung mittels eines gängigen script-Tags in der HTML-Datei. Zum anderen macht Facebook React über die Online-IDEs CodePen, CodeSandbox und StackBlitz verfügbar. Letztendlich findet man alle JavaScript-Bibliotheken für die React-Programmierung auch im Node.js-Repository. Installiert man die Bibliotheken als npm-Package, so stehen sie als Moduln über eine require-Anweisung in einem JavaScript-Programm zur Verfügung.
Neuanlage einer React-App
Im Node.js-Repository hat Facebook auch ein CLI (Call Level Interface) für die Neuanlage einer React-App bereitgestellt: Create React App. Man findet dieses CLI im gleichnamigen npm-Package create-react-app. Nach dessen Installation über npm install -g create-react-app legt man ein neues Entwicklungsprojekt mittels des Kommandos create-react-app proj-name an. Das npm-Package richtet daraufhin einen Projektordner mit allen erforderlichen Ressourcen und notwendigen Scripts für die Entwicklung einer React-App ein. Das neu eingerichtete Entwicklungsprojekt proj-name eignet sich auch für Debugging/Test und für die Bereitstellung zum Betrieb der React-App in einer Produktionsumgebung.JSX von Facebook entspricht nicht JSX von DeNA
JSX von Facebook darf nicht mit der gleichnamigen Programmiersprache JSX der DeNA aus Japan verwechselt werden. Beinahe zeitgleich wie Facebook befasste sich das japanische Softwarehaus DeNA aus Tokio im Rahmen ihrer Mitarbeit beim W3C-Konsortium mit der Weiterentwicklung oder Verbesserung von JavaScript. Daraus entstand in einem Forschungsprojekt JSX als schnellere, typsichere, objektorientiere und leichter verständlichere Programmiersprache. Diesen Sachverhalt muss man bei der Programmierung beachten, da es viele Packages im npm-Repository gibt, die sich auf JSX der DeNA und nicht auf JSX für React beziehen.
Umfassende Informationen zum Arbeiten mit der neuen Web-App findet man im Projektordner in der Datei README.md. Sie enthält Anleitungen, um die neue React-App zu starten, um den bereitgestellten Test-Runner im interaktiven Watch-Mode zu aktivieren oder einen Build der App für die Produktion durchzuführen.Zudem verweisen die in der README.md-Datei enthaltenen URLs auf weiterführende Anleitungen, um eine Progressive Web App (PWA) zu programmieren, das Deployment (Software-Verteilung) durchzuführen oder die Größe der Bundle-Datei zu analysieren. Alle aufgeführten URLs sind mit der Homepage von Create React App verknüpft, die Facebook speziell eingerichtet hat.

Die Create React App von Facebookerzeugt für ein React-Projekt eine einheitliche Ablagestruktur, generiert einen Programmrahmen, stellt dessen npm-Infrastruktur bereit und konfiguriert die Werkzeuge für Programmierung, Test und Deployment(Bild 3)
Simon
Die Ablagestruktur eines React-Projekts besteht aus den drei Verzeichnissen: node_modules, public und src. Wie in JavaScript-Projekten üblich enthält der node_modules-Ordner alle npm-Packages, welche die Anwendung und Entwicklungswerkzeuge benötigen. Der public-Ordner umfasst den statischen Inhalt der React-App, insbesondere die index.html-Datei, die beim Starten der Web-App der Aufruf eines HTTP-Requests anzieht. Im src-Ordner findet man den Quellcode der Anwendung und die zugehörigen Ressource-Dateien für Styling und Test. Zusätzlich enthält das Hauptverzeichnis des Projekts die package.json- und die bereits erwähnte README.md-Datei (Bild 3).
Aufbau eines React-Projekts und dessen Einsatz für die tägliche Arbeit
Der src-Ordner entspricht also dem eigentlichen Entwicklungsordner; die dortige Datei app.js enthält den generierten Programmrahmen mit dem Quellcode in JavaScript/TypeScript für die initiale React-Komponente der Web-App – auch Top- oder Root-Komponente genannt. Die zugehörigen CSS-Styles stehen in der Datei app.css; app.test.js spezifiziert den initialen Unit-Test für die Top-Komponente der Web-App. Die Datei index.js dient der Konfiguration der React-App und dem Starten der Anwendung; ihr Quellcode führt das initiale Rendern der Top-Komponente durch. Die globalen CSS-Styles von index.js enthält die Datei index.css.JSX macht HTML-Anweisungen zu JavaScript-Code
React orientiert sich mit der Einbettung von JSX mehr an JavaScript als an der HTML-Syntax an. Generell verwendet das React-DOM camelCase als Namenskonvention für Eigenschaften (innenliegende Großschreibung in Wörtern, auch Binnenmajuskeln oder Kamelversalien genannt) anstatt der HTML-typischen Schreibweise. So verwendet das React-DOM className für den Namen der Klasse eines HTML-Elements (analog HTMLElementObject.className) und nicht nur class wie HTML-Tags, um das class-Attribut auszuzeichnen. JSX und damit das React-DOM richtet sich bei den Elementen eher an der Namensgebung des HTML-DOMs. So wird in JSX aus dem tabindex von HTML im React-DOM tabIndex oder analog aus dem for-Attribut der HTML-Elemente (label, output) in JSX htmlFor. Allerdings setzt JSX nicht innerHTML wie das HTML-DOM ein, sondern eine eigene Namenskreation dangerouslySetInnerHTML.
Die package.json-Datei enthält die drei standardmäßig eingerichteten npm-Scripts start, build und test. Führt man über eine Eingabeaufforderung (Windows) oder einem Terminalfenster (Linux, macOS) den Befehl npm start aus, so nimmt dieser einen Compile & Build vor und führt die React-App auf dem Port 3000 über http://localhost aus. Sobald der lokale HTTP-Server startet, steht die Hot-Reload-Funktionalität von React zur Verfügung: Verändert der Programmierer den Quellcode, so führt der lokale Webserver diesen sofort aus und man kann Tests mit den Änderungen durchführen. Sollte der geänderte Quellcode fehlerhaft sein, so zeigt React im Webbrowser die Fehlerquelle direkt im Quellcode mit Angabe der Zeilennummer an (Bild 4).

Hot-Reloading von Reactaktualisiert nicht nur die Web-App, sondern zeigt auch Fehler im Quellcode der Web-App direkt im Webbrowser an(Bild 4)
Simon
Das zweite npm-Script npm run build legt einen neuen build-Ordner mit den optimierten Ausführungsdateien der React-App an. Vom build-Ordner ausgehend kann man ein Deployment der Web-App aufsetzen. Soll die App nicht auf dem Root-Verzeichnis des Webservers laufen, so muss man über einen speziellen Eintrag die relative Homepage-URL in der package.json-Datei definieren. Als Testrunner setzt Create React App das von Facebook entwickelte Testing-Framework für JavaScript Jest ein. Über das dritte npm-Script npm run test kommen die Unit-Tests mit Jest zur Ausführung.
Projektumgebung an die individuellen Anforderungen anpassen
Facebook empfiehlt für die Neuanlage eines React-Entwicklungsprojekts, das npm-Package create-react-app einzusetzen. Prinzipiell generiert die Create React App alle notwendigen Dateien für Entwicklung, Test, Deployment und richtet diese zusammen mit einem Programmgerüst (Boilerplate) für eine React-App optimal ein. Dazu nimmt Create React App für die Entwicklungstools alle notwendigen Einträge in den Konfigurationsdateien vor. Die Kommandoschnittstelle von Create React App kennt eine Reihe von Befehlsoptionen, von denen man eine Übersicht durch Aufruf von create-react-app mit dem --help-Parameter erhält.Einige der Befehlsoptionen ermöglichen es, die initiale Einrichtung des React-Projekts an eigene Vorstellungen anzupassen. Dazu gehören die beiden Optionen: --scripts-version und --template. Die erste Befehlsoption bezieht sich auf die vier eingerichteten npm-scripts: start, build, test und eject. Um diese nicht bei jedem neuen React-Projekt von Hand anpassen zu müssen, definiert man ein eigenes npm-Package und übergibt dieses an Create React App nach der Befehlsoption --scripts-version <alternatives-nmp-Package>. Das GitHub-Repository von Create React App enthält im packages-Bereich die ursprünglichen React-Scripts.Von dessen scripts-Unterverzeichnis ausgehend nimmt man die Anpassungen oder Erweiterungen vor. Stellt man diese anschließend über ein npm-Package im Nodes.js-Repository bereit, greift Create React App direkt darauf zu. Standardmäßig verwendet Create React App bei der Generierung des Programm-Gerüsts das Template cra-template.Rapid Prototyping von React-Komponenten
Online-Editoren für HTML, CSS und JavaScript wie CodePen, CodeSandbox, jsFiddle, JS Bin oder StackBlitz unterstützen schnelles Prototyping für React-Komponenten. Der Einsatz eines Online-Editors parallel zur Entwicklungsumgebung erlaubt sofortiges Testen von React-Quellcode – es entfällt der notwendige Aufwand im Projekt für das Einrichten und auch sonstige zusätzliche Vorarbeiten.
Um ein alternatives oder selbst bereitgestelltes Template zu verwenden, setzt man den zweiten Befehlsparameter --template ein. Alternative Templates findet man im Nodes.js-Repository über den Suchstring cra-template-*. Ein React-Projekt für TypeScript erzeugt das Template cra-template-typescript durch den CLI-Befehl: create-react-app mein-proj --template typescript. Für die Anlage eines eigenen Template befindet sich im Benutzerhandbuch auf der Homepage von Create React App im Bereich Custom Templates eine ausführliche Anleitung.
Vorgaben eines React-Projekts für individuelle Entwicklung überarbeiten
Facebook hat in der package.json-Datei als vierten npm-Script npm run eject eingerichtet; dieser entfernt alle Voreinstellungen aus den vorhandenen Konfigurationsdateien. Achtung: Alle von npm run eject vorgenommenen Änderungen können nicht mehr rückgängig gemacht werden. Das bedeutet, nach einer Ausführung des run eject-Scripts lässt sich das React-Projekt nicht mehr in seinen ursprünglichen Zustand überführen. Daher sollte man das Script nur aufrufen, falls die Voreinstellungen und die dazugehörenden Konfigurationen tatsächlich für das eigene React-Projekt ungeeignet sind.Dieses zusätzliche npm-Script sollte man also in der Regel nur zur Ausführung bringen, falls man andere Utilities für die eigene Entwicklung verwenden möchte als die von Facebook programmierten und voreingestellten. Davor muss man eine Commit-Operation für alle offenen Änderungen im Git-Repository durchführen oder falls man kein Git einsetzt, den .git-Ordner komplett löschen. Das run eject-Script erzeugt im Projektordner ein neues config-Verzeichnis und legt dort alle für die React-App notwendigen Konfigurationsdateien mit den Build-Abhängigkeiten und den neuen Scripts ab. Zum Schluss gibt das run eject-Script eine URL-Adresse aus, die auf ein von Facebook vorbereitetes Formular verweist.Abschließend installiert man noch die zusätzlich für das Projekt gewünschten Entwicklungstools und passt deren Einstellungen in den Konfigurationsdateien entsprechend im config-Ordner an (Bild 5).
Das npm-Script run eject entferntaus einem React-Projekt sämtliche Abhängigkeiten der Entwicklungswerkzeuge und erzeugt neue voneinander unabhängige Konfigurationsdateien(Bild 5)
Simon
In der Regel benötigt man das run eject-Script nur beim Einsatz weiterer Nodes.js-Module, die auch auf die seitens Create React App verwendeten Module zugreifen. Die daraus resultierenden Abhängigkeiten müssten auch beim Einsatz dieser Module in der Create React App Berücksichtigung finden. Erst bei häufig ähnlichen Projekten macht die Entwicklung eines eigenen Template für die Projektanlage mit Create React App Sinn.Öffnet man nach Aufruf des npm run eject-Scripts, die vom React-Team genannte URL, so erscheint ein vorbereitetes Formular das, einige Daten über den Einsatz von React und der Create React App erhebt. Anhand dieses Formulars ermittelt das React-Team die gemachten Erfahrungen mit dem Create React App-CLI und die Gründe, die zum Aufruf des run eject-Scripts führten. Speziell zielt das Formular darauf ab, eventuelle Fehler, Mängel oder Probleme mit React oder der Create React App zu erfassen. Im Formular kann man auch Bewertungen zum Create React App-CLI und den von Facebook vorkonfigurierten Entwicklungstools Webpack, Babel und ESLint vornehmen.
Facebook positioniert React als strategische Schlüsseltechnologie
Die über das Formular erfassten Daten wertet Facebook kontinuierlich aus, in manchen Fällen nimmt das React-Team auch direkten Kontakt per E-Mail mit den Entwicklern auf. Damit stellt das React-Team sicher, die Beweggründe vollständig und korrekt verstanden zu haben. Eine sorgfältige Ermittlung spezifischer Anforderungen bei den Entwicklern trägt maßgeblich zum besseren Verständnis beim React-Team bei. Nur richtig und vollständig erfasste Änderungs- oder Erweiterungswünsche dürfen als Entscheidungsgrundlage in die Weiterentwicklung der Create React App einfließen. Schließlich dienen diese Erhebungen bei Facebook dazu, die Create React App an die Anforderungen der Entwicklungsgemeinde von React anzupassen.Die wichtigsten Änderungswünsche fließen anschließend in eine neue Version der Create React App und auch in React ein. Beispielsweise hat Facebook eine Unterstützung für die Programmiersprache TypeScript, weitere Styling-Optionen (Sass, CSS Moduln, PostCSS) oder die Entwicklungswerkzeuge Apollo, Babel-Makros von Dritthersteller, MDX oder Realy Modern in Create React App eingebaut. Diese Vorgehensweise von Facebook zielt klar darauf ab, die Akzeptanz von React in der Anwendergemeinde zu verbessern und die Verbreitung bei den Entwicklern zu vergrößern. Dies verdeutlicht auch, welch hohen strategischen Stellwert die React-Technologie derzeit in der Anwendungsentwicklung bei Facebook besitzt.Elemente als Grundbausteine für den sequentiellen Aufbau einer Webseite
Analog den HTML-Elementen, die man als Grundbausteine des HTML-DOMs ansehen kann, bilden React-Elemente das Fundament für die Beschreibung des React-DOMs: dem Virtual-DOM. Bei diesen React-Elementen handelt es sich um JavaScript-Objekte, die als Meta-Objekt eine React-Komponente oder einen DOM-Knoten und seine Properties/Attribute beschreiben. Ein React-Element entspricht einer Repräsentation eines DOM-Elements im Virtual-DOM. Das React-Element enthält nur Informationen über ihren Komponententyp (zum Beispiel eine Schaltfläche/Button), seine Properties/Attribute (zum Beispiel die Farbe der Schaltfläche/Buttons) und Zusatzinformationen über alle seine Kind-Elemente.Bei einem React-Element handelt es sich nicht um eine Ausprägung oder Bestandteil einer Webseite – vielmehr um eine Beschreibung, wie man diesen konstruiert. Jedoch bieten React-Elemente dem Programmierer keine aufrufbaren Methoden an. Als Programmierer legt man ein React-Element über die React-Methode React.createElement(type, props, children) an. Der type entspricht einer Zeichenkette/String, der einen DOM-Knoten über einen Tag-Namen (zum Beispiel div) identifiziert. Der type wird durch eine React-Komponente über eine Klasse/Funktion beschrieben – man spricht von einer benutzerdefinierten Komponente.Async Rendering und Lifecycle-Methoden
Das React-Team will zukünftig Asynchrones Rendering für ein besseres Laufzeitverhalten der Apps unterstützen. Das geplante Async Rendering soll vor allem zwei Problemstellungen lösen: Keine Blockierung von Updates mit höherer Priorität und Aussetzen des Rendering während der Datenbereitstellung. Im Rahmen der Pilotierung von Async Rendering ermittelte Facebook Schwachstellen bei der Einbindung der Lifecycle-Methoden seitens der Programmierer. Alle festgestellten problematischen Lifecycle-Methoden erhalten seit React Version 16.x einen Alias mit dem Präfix UNSAFE_. Seit Version 17 (Oktober 2020) existieren die alten Lifecycle-Methoden ohne den UNSAFE_-Präfix nicht mehr. Ergänzend führte Facebook zwei neue Lifecycle-Methoden ein: getDerivedStateFromProps und getSnapshotBeforeUpdate.
Beim zweiten Parameter der createElement-Methode props handelt es sich um ein in geschwungenen Klammern { } stehendes einfaches Objekt. Dieses Objekt kann DOM-Attribute von DOM-Knoten wie type, src, href oder alt enthalten. Alternativ können sich beliebige Werte für React-Komponenten wie Arrays oder andere Objekte darin befinden. Als Programmierer erhält man innerhalb des Komponenten-Body über this.props Zugriff. props repräsentieren Objekt-Eigenschaften/Attribute aber keine Zeichenketten wie HTML-Attribute. Ausgenommen von dieser Bedingung sind reservierte Wörter wie className oder htmlFor. Beim letzten Parameter children handelt es sich entweder um ein einzelnes ReactNode-Objekt (eine Zeichenkette oder eine Zahl als Textinhalt für einen Knoten), ein React-Element (dieses kann einen Baum von weiteren Elementen enthalten) oder ein Array von ReactNodes.
JSX bringt React mit JavaScript und HTML zusammen
Wie jedes XML-Element besitzt ein JSX-Tag einen Tag-Namen, Attribute und Kind-Elemente. Beispielsweise deklariert die JSX-Anweisung
const element = <h1>Ich bin ein JSX-Element</h1>
eine Variable. JSX erlaubt es, HTML-Elemente zusammen mit React-Komponenten zu programmieren und diese im DOM zu platzieren, ohne dass man die sonst üblichen Methoden wie createElement() oder appendChild() aufrufen muss. JSX konvertiert HTML-Tags in React-Elemente mittels der render()-Methode des ReactDOM. JSX ermöglicht es, Quellcode direkt für das User-Interface zu schreiben, ohne ständig auf die React-Methode createElement() zurückgreifen zu müssen.Der Programmierer schreibt mittels JSX React-Elemente und React überführt diese ins HTML-DOM, so dass der Programmierer über die vollständige Mächtigkeit von JavaScript verfügt. Somit erleichtert JSX das Schreiben und Hinzufügen von HTML-Quellcode in React wesentlich, so dass man als Programmierer produktiver arbeitet. Dies verdeutlicht, weshalb man in der Entwicklung mit React nicht auf JSX verzichten sollte. JSX-Anweisungen befinden sich direkt inline im JavaScript-Quellcode. Dieses Inline-JSX überführt ein Präprozessor in React-Code, der regulärem JavaScript (ECMAScript) entspricht, dieser Vorgang nennt sich JSX-Transform.JSX-Transform führt in einem React-Projekt der Babel-Transcompiler/Transpiler aus; dazu verwendet Babel ein spezielles Plugin für JSX. Das abschließende Packaging der bundle.js-Datei übernimmt Webpack unter Einbezug der React-Library. Das JSX-Plugin für Babel befindet sich im npm-Package @babel/plugin-syntax-jsx. Babel kompiliert JSX zu React.createElement()-Aufrufe. Um Babel für JSX-Transform einzusetzen, benötigt man eine Installation der npm-Packages @babel/core und @babel/cli. Die Ausführung des erzeugten ECMAScript-Codes im Webbrowser erfordert zusätzlich noch eine Installation das npm-Package @babel/polyfill. Der Einsatz des JSX-Plugins im Babel-Transcompiler erfolgt über verschiedene Wege: JSX erlaubt die Neuanlage von React-Komponenten direkt über HTML- oder selbst-definierte (individuelle) Tags; dabei orientieren sich deren Attribute und ihre Werte an der zugehörigen React.createElemente()-Methode. Die createElement()-Methode besitzt folgenden Aufbau:
React.createElement(
type,
[props],
[...children]
)
Als Ergebnis liefert diese Methode entweder HTML-Quellcode oder einen Generator für eine React-Komponente zurück. In JSX entspricht der type-Parameter einem Tag-Namen (name), das optionale props-Array verschiedenen Schlüssel-Wert-Paare (key1=value1 key2=value2…); wobei die optionalen children-Parameter auf eine Schachtelung weiterer JSX-Anweisungen, das heißt React-Komponenten abzielen. Somit wird Nesting von JSX-Anweisungen innerhalb anderer JSX-Anweisungen unterstützt. Ein Schlüssel-Wert-Paar stellt entweder die Attribut-Definition einer HTML-Anweisung oder die prop-Eigenschaften einer React-Komponente dar, um die Attribute einer React-Komponente (props) mit Werten zu bestücken.Analog der Vorgehensweise in React erlaubt auch JSX eine Konfiguration von Elementen über Ausdrücke (Expressions), auf die man in geschwungenen Klammern {} verweist. Das Konstrukt der Expressions zielt darauf ab, statischen Inhalt einer HTML-Seite mit dynamischen Werten zu bestücken. Eine Expression kann vollständigen JavaScript-Quellcode aufnehmen, so dass man darüber auch Berechnungen durchführen kann.Erlaubt ist auch das Einbinden von JavaScript-Kommentaren über /*… */ oder // allerdings müssen diese in geschwungenen Klammern mit anschließendem Komma stehen, beispielsweise: { / },. Für komplexe Operationen implementiert man eine JavaScript-Funktion. Über einen Ausdruck erhält man Zugriff auf die Werte von Variablen und über den Punkt-Operator auch einen Zugriff auf die Eigenschaften (Properties) von Komponenten.Analog dem Zugriff auf die Eigenschaften und damit auf die Werte einer Komponente erhält man über den Punkt-Operator auch Zugriff auf ihre Methoden: MyComponent.computeValue(…). Somit erlaubt eine Expression die Ausführung von Methoden einer Komponente und damit auch die Instanziierung einer Komponente oder das Setzen der Werte ihrer Properties (props).
Konditionales Rendering und Rendering
Rendering erfolgt immer ausgehend von einem React-Element, welches das React-Laufzeitsystem über die return()-Anweisung erhalten hat. Soll kein Rendering durchgeführt werden, so muss man darauf achten, dass return() entweder null, undefined, einen booleschen Wert (true, false) oder ein leeres Array [] zurückliefert. Um eine Komponente aus dem Rendering auszuschließen, setzt man den Rückgabewert ihrer render()-Methode auf null. Allerdings muss man beachten, dass React trotzdem alle anderen Laufzeitmethoden für diese Komponente weiterhin ausführt.Eine bedingte Zusammensetzung von Komponenten lässt sich in JSX über die if/else-Anweisung von JavaScript umsetzen:
…
// Berechne Wert bewertung
…
if (bewertung>vorgabeWert) {
return <div> … /div>
} else {
return <div> … </div>
}
Als Kurzform des if-Statements setzt man den bedingten (ternären) Operator: condition ? expr1 : expr2. Ist die condition des Bedingungsoperators erfüllt, kommt expr1 zur Ausführung, andernfalls greift expr2. Dabei stellen expr1 und expr2 JSX-Anweisungen dar, die das return()-Statement alternativ zurückliefert. Innerhalb einer Methode sollte man darauf achten, möglichst wenige return()-Anweisungen zu verwenden. Dies erreicht man sehr leicht über React-Element-Variablen. In einer Variablen speichert man die JSX-Elemente und initialisiert diese über eine if-Bedingung, falls man sie benötigt – andernfalls erhält die Variable den null-Wert und wird nicht berücksichtigt.React-Anfänger machen häufig den Fehler, dass sie über das return()-Statement mehrere JSX-Tags für das Rendering zurückliefern, was zu einem Fehler führt. Erfahrene HTML-Programmierer tendieren dazu, mehrere JSX-Tags in ein div-Element oder leeres <> einzubetten, so dass der Fehler beim Rendering nicht auftritt. Alternativ liefert man, anstatt mehrere JSX-Tags ein Array mit diesen als einzelne Einträge zurück; was den Fehler ebenfalls verhindert. Facebook hat React Fragments eingeführt, um mehrere JSX-Tags zu gruppieren, so dass diese als Gruppe im DOM behandelt werden:
return (
<React.Fragment>
<div> … </div>
<div> … </div>
</React.Fragment>
)
Mit React programmiert man das User-Interface einer Web-App, die sogenannte View. Dabei setzt man die View aus einer Reihe voneinander unabhängiger, isolierter und wiederverwendbarer Komponenten zusammen. Jede dieser Komponenten implementiert man als eine JavaScript-Funktion, die man mit Input-Parametern aufruft und die eine Ausgabe zurückliefert, für die React das Rendering durchführt (Bild 6). Wenn man Funktionen wiederverwendet, so führt man mit diesen Komponenten eine Wiederverwendung durch, kombiniert mehrere davon und erhält so zum Schluss das gewünschte User-Interface der Web-App.

Eine React-App besteht aus einzelnen Komponenten,die separat erstellt und aus denen React das User-Interface zum Schluss zusammenbaut(Bild 6)
Simon
Um eine Web-App mit React zu entwickeln, betrachtet man zu Beginn das zu programmierende User-Interface. Dieses User-Interface zerlegt man in kleinere, einzelne Einheiten, die jede für sich betrachtet, eine bestimmte Aufgabe übernimmt. Jede der Einheiten repräsentiert eine Komponente, die man isoliert programmiert und später in das User-Interface übernimmt. Für die Zerlegung des User-Interface der Web-App gibt es in der Regel verschiedene, alternative Aufteilungen. Allerdings sollte man die Aufteilung des User-Interface in Einheiten mit der Zielsetzung ihrer Wieder- beziehungsweise Mehrfachverwendung vornehmen.Konzeptuell entspricht eine Komponente einer JavaScript-Funktion, der man beim Aufruf Input-Parameter übergibt. Als Rückgabe liefert die Funktion React-Elemente zurück, die das Erscheinungsbild des User-Interface beschreiben. Bei den Übergabeparametern der Funktion handelt es sich um die Eigenschaften der Komponente; in der React-Terminologie Properties oder kurz props genannt. Um verschiedenartige Informationen am Bildschirm auszugeben, ruft man die Funktion mit anderen Daten auf.Die zentrale Komponente der React-App nennt man häufig Root- oder Wurzel-Komponente; diese befindet sich in der Datei App.js im src-Verzeichnis des Projektordners. In die App.js-Datei importiert man alle weiteren Komponenten, verwendet deren Funktionen an der passenden Stelle und baut so schrittweise das komplette User-Interface der Web-App auf. Befindet sich beispielsweise eine Tabelle mit Datenwerten im User-Interface, so zerlegt man diese in zwei Komponenten: den Tabellenkopf und den Tabellenkörper mit den Datenwerten. Die JavaScript-Funktion für den Tabellenkopf programmiert man in der Datei kopf.js:
import React from 'react'
export default function Tabellenkopf() {
return (
<thead>
<th> Kundenname </th>
<th> Kundenbetreuer </th>
</thead>
)
}
Entsprechend befindet sich die JavaScript-Funktion Tabellenkoerper() in der Datei koerper.js:
import React from 'react'
export default function Tabellenkoerper() {
return (<tbody>
<tr>
<td> Otto Bauer</td>
<td> Aidlingen</td>
</tr>
<tr>
<td> Udo Heikenwälder</td>
<td> Herrenberg</td>
</tr>
<tr>
<td> Renate Simon</td>
<td> Illmensee</td>
</tr>
</tbody>
)
}
Die von Create React App generierte zentrale Root-Komponente in der JavaScript-Datei App.js muss Quellcode für HTML/JavaScript, das heißt ein JSX-Element für das React-DOM zurückliefern, dies erreicht die render()-Methode von React. Insgesamt passt man den Quellcode von App.js wie folgt an:
import React, { Component } from 'react';
import './App.css';
import Tabelle from './tabelle'
export default class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<Tabelle />
</header>
</div>
)
}
}
Führt man im Projektordner das Script npm start aus, so erfolgt ein Compile des Quellcode und der lokale Webserver startet zusammen mit einem Webbrowser die React-App (Bild 7).

Das im Webbrowser angezeigte User-Interfacesetzt der Entwickler aus verschiedenen, einzelnen in React programmierten Komponenten zusammen(Bild 7)
Simon
Generell haben React-Komponenten immer die folgenden Eigenschaften: sie besitzen einen Namen, sie haben nur einen Wurzelknoten und sie müssen für die Darstellung am Bildschirm in ein Zielelement im DOM gerendert werden. Der Name einer Komponente beginnt immer mit einem Großbuchstaben; dabei verwendet man bei der Namensvergabe die CamelCase-Konvention. Dadurch unterscheidet man Komponenten leicht von HTML-Elementen (Tags), da diese mit einem Kleinbuchstaben beginnen. Der React-Compiler erzeugt nur für Namen mit anfänglichem Großbuchstaben eine createComponent()-Methode. Als Rückgabe mittels return() liefern Komponenten immer ein React-Element zurück.Das User-Interface einer React-App setzt sich aus einzelnen Komponenten nach dem Baukasten-Prinzip zusammen: Eine Komponente kann andere Komponenten beinhalten; diese nennt man die Kinder der Komponente. Komponenten können Daten als Eingabe empfangen – dabei handelt es sich nach der React-Terminologie um Properties (kurz: props) –diese speichern Eigenschaften oder Attribute. Zusätzlich können Komponenten eigene (private) Daten besitzen – in der React-Terminologie states genannt. React kennt verschiedene Typen von Komponenten, diese gruppiert man nach ihrer Realisierung: Komponenten, die eigene, private Daten (states) besitzen, implementiert der Programmierer immer als JavaScript-Klasse – in der React-Terminologie Class-Components genannt.Eine Komponente reagiert normalerweise, wenn sich ihr state (eigene Daten) ändert – aus diesem Verhalten leitet sich der Name für die User-Interface-Library ab: React. Die Änderung muss immer über einen Aufruf von this.setState() erfolgen; er triggert ein erneutes Rendern; dabei bezieht das React-Laufzeitsystem auch alle Unter/Kind-Komponenten mit ein. Komponenten ohne states implementiert der Programmierer als JavaScript-Funktion – sie heißen Functional-Components, manchmal auch Stateless-Components genannt.Einer Functional-Component kann man auch Daten mittels Properties (props) übergeben, diese sind aber in einer Class-Component definiert und dort nicht veränderbar (read-only: immutable). Dabei stellen die props einer Komponente Eingabedaten dar, die an ihre Kind-Komponente weitergereicht werden. Bei den props handelt es sich entweder um eine Zeichenkette/String oder um ein JavaScript-Objekt:
function ParentComponent(){
return <ChildComponent name="Otto" alter={32} />
}
function ChildComponent(props){
return <p> Hallo, mein Name ist {props.name}, ich
bin {props.alter} Jahre alt </p>
}
Eine Class-Component stammt immer von der React.Component-Klasse ab. Im Unterschied zu den props definiert eine Class-Component ihre states als Variable und übernimmt deren Verwaltung. Anders als eine Functional Component muss eine Class-Component immer die render()-Methode implementieren. Zusätzlich müssen beide Typen von Komponenten eine return-Anweisung besitzen. Auch eine Class-Component kann Daten an ihre Kinder (Bauteile) weiterreichen – dies erfolgt über props; allerdings muss der Programmierer dabei auf das Schlüsselwort this zurückgreifen, im obigen Beispiel: {this.props.name} oder {this.props.alter}:
class ParentComponent extends React.Component {
render () {
return(
<p> Hallo, mein Name ist {this.props.name}, ich
bin {this.props.alter} Jahre alt </p>
)
}
}
// Ausfuehrung der Komponente mit Werten fuer die
// Parameter
ReactDOM.render(
<ParentComponent
name="Otto"
alter={32}/>, document.getElementById("root"))
Properties, abgekürzt: props, stehen für die Eigenschaften beziehungsweise Attribute einer Komponente. Bei props handelt es sich in der Regel um JavaScript-Objekte, die in React mit Read-Only-Komponenten gleichzusetzen sind. Ein solches Property-Objekt speichert den Wert von Attributen eines Tags – vergleichbar den HTML-Attributen. Allerdings können Properties innerhalb einer Komponente nicht verändert werden – sie sind unveränderbar (immutable). Jedoch kann man innerhalb einer Komponente derartige Attribute als props hinzufügen.
Einsatz von props und states innerhalb einer Anwendung
Der Zugriff auf diese Attribute in der Komponente erfolgt mittels this.props; man verwendet diese, um dynamisch Daten über die render()-Methode anzuzeigen. Mittels props reicht man Daten von einer Komponente an eine andere Komponente weiter – vergleichbar einem Argument bei einer Funktion. Daher kann man innerhalb einer render()-Funktion auch direkt eine Property für die zugehörige Klasse eineKlasse mittels der JSX-Anweisung {this.props.name} definieren. Die Übergabe eines zugehörigen Werts für ein so definiertes Property erfolgt außerhalb der Klasse innerhalb einer render()-Funktion mittels der JSX-Anweisung <eineKlasse name="Wert" />.Eine Wertzuweisung über JavaScript innerhalb und außerhalb einer Klasse nimmt die defaultProps()-Methode vor: eineKlasse.defaultProps = { name: "Wert" }; dies wirkt wie ein Standardwert; er greift, sollte kein anderer Wert seitens der App gesetzt werden. Innerhalb einer App kann man state und props gleichzeitig verwenden: Setzt man innerhalb einer Eltern-Komponente einen state, so kann man diesen an eine Kind-Komponente über props weiterreichen.Der state einer Komponente ist veränderbar; diese Veränderung erfolgt ausgehend von einer Benutzer-Interaktion oder über einen Event. Um den state zu aktualisieren, ruft man die setState()-Methode innerhalb oder direkt über die Komponente auf. Den Anfangszustand eines state setzt man über die getInitialState()-Methode. Grundsätzlich führt React die setState()-Methode asynchron aus; manchmal werden mehrere setState()-Methoden aus Performancegründen sogar zusammengefasst und auf einmal abgearbeitet. Daher sollte man Aktualisierungen des Zustands, die vom aktuellen Zustand einer Komponente abhängen nicht durch einen Zugriff auf this.state, sondern mittels einer Funktion als Argument von setSate() oder über eine Arrow-Funktion realisieren.Programmierumgebung anpassen und mit zusätzlichen Tools erweitern
Für die Entwicklung mit React sollte man entweder Visual Studio Code oder WebStorm einsetzen (siehe Teil 2). Nur diese beiden Werkzeuge unterstützen ein Debugging einer React-App direkt innerhalb der Entwicklungsumgebung. Dazu muss man allerdings in Visual Studio Code aus dem Marketplace den Debugger for Chrome installieren. Anschließend richtet man innerhalb des Projekts über VS Code über Run>Add Configuration… eine launch.json-Datei ein. Die von VS Code erzeugten Einträge in launch.json passt man an die Vorgaben eines React-Projekts an:
{
"version": "0.2.0",
"configurations": [
{
"name": "Chrome",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}/src",
"sourceMapPathOverrides": {
"webpack:///src/*": "${webRoot}/*"
}
}
]
}
Für WebStorm benötigt man entgegen den Angaben von Facebook keine zusätzliche Extension; man muss lediglich bei den Run Configurations den Eintrag JavaScript Debug auswählen. Facebook hat für das Debugging einer React-App über den Webbrowser die React Developer Tools entwickelt. Dazu installiert man in den Webbrowsern Chrome, Firefox oder Edge die zugehörige Erweiterung. Nach der Installation enthält der Debugger im Webbrowser zwei weitere Listeneinträge Components und Profiler; beide mit dem React-Icon als Präfix. Zusätzlich gibt es im Web ein interaktives Tutorial von Facebook für den Einsatz der React Developer Tools.Für das Erkunden von React-Komponenten stehen zwei weitere Entwicklungstools von Drittherstellern zur Verfügung: Storybook for React oder alternativ React Styleguide. Bei beiden handelt es sich um npm-Packages, die dem Entwickler eine Komponenten-Library zugänglich machen. Diese kann man nach geeigneten Komponenten für die jeweilige React-App durchsuchen. Die states und props der Komponenten lassen sich direkt erkunden und testen. Für die Dokumentation von React-Komponenten findet man auf GitHub das npm-Package react-docgen. Das Tool verfügt über eine interaktive Kommandoschnittstelle (CLI) und ein API, um es an die eigenen Belange beim Parsen anzupassen. Neben JavaScript unterstützt react-docgen auch Flow und TypeScript.
Komponenten-Kommunikation
Eine React-App entspricht einer Hierarchie von Komponenten, die untereinander kommunizieren, um so Daten auszutauschen. Ergänzend sorgt der unidirektionale Data-Flow für einheitliche Zuständigkeitsbereiche, die man grundsätzlich bei der Kommunikation berücksichtigen muss. Aufgrund der hierarchischen Beziehung zwischen den Komponenten findet die Kommunikation immer zwischen Eltern- und Kindknoten statt. Im ersten Fall reicht die Eltern-Komponente beim Aufruf der Kind-Komponente Daten an diese weiter:
// Eltern-Komponente in der Datei App.js:
import React, { Component } from 'react';
import './App.css';
import Kind from './Kind'
class App extends Component {
constructor(props) {
super(props);
this.state = {
name: "Vom Elternknoten zum Kind",
}
}
render() {
return (
<div>
<h1>Übergabe: Vom Eltern- zum Kindknoten</h1>
<Kind elternProp = {this.state.name} />
</div>
);
}
}
export default App;
Über das props-Objekt erlangt die Kind-Komponente Zugriff auf die Datenwerte der Eltern-Komponente. Ein Aufruf von this.props sammelt alle übergebenen props in einem Array; sie können dort über einen Iterator/Index gelesen werden. Die Kommunikation über Properties erfolgt von oben (den Elternknoten) nach unten zu den Kindknoten. React unterstützt eine Kombination von state und props; so kann eine Eltern-Komponente ihren state als props an eine Kind-Komponente weiterreichen:
// Kind-Komponente in der Datei Kind.js:
import React, { Component } from 'react';
import './Kind.css';
class Kind extends Component {
render() {
return (
<div>
<h1>Beispiel: state als props übergeben</h1>
<h4>Im Kindknoten kam:
{this.props.elternProp}</h4>
<h4>als Wert vom state.name des Elternknotens
an!</h4>
</div>
);
}
}
export default Kind;
Die umgekehrte Richtung – eine Kommunikation der Kind- zur Eltern-Komponente kann ebenfalls über props und state erfolgen. Zusätzlich möglich ist eine Kommunikation über Event-Handling: Im Elternknoten definiert man den Event-Handler als JavaScript-Funktion. Diese JavaScript-Funktion übergibt man bei der Einbettung der Kind- in die Eltern-Komponente mittels eines im Kindknoten definierten props-Attribut. In diesem Fall entspricht die Callback-Funktion dem Property und das Event dem Aufruf der Callback-Funktion:
import React from 'react';
import datenJSON from './daten';
import Kind from './Kind';
import './App.css';
// Event-Handler mit zusaetzlichem Uebergabeparameter
function funktionOnClick(infoObjekt){
const alertInfo = Object.entries(infoObjekt)
.map(information => `${information[0]}: ${information[1]}`)
.join('\n');
alert(alertInfo)
}
function App() {
return (
<div className="artikel">
<h1>Aktueller Artikelbestand</h1>
{/* JSON-Daten im Array datenJSON
an Kind-Komponente weiterreichen
*/ }
{datenJSON.map(element => (
<Kind
name={element.name}
artikelnr={element.artikelnr}
preis={element.preis}
bestandteile={element.bestandteile}
infoObjekt={element.infoObjekt}
funktionEltern={funktionOnClick}/>
))}
</div>
)
}
export default App;
In der Kind-Komponente definiert man einen Event, beispielsweise onClick, und übergibt vom Elternknoten eine Referenz auf den in der Eltern-Komponente definierten Event-Handler mittels einer Property an die Kind-Komponente. Der Kindknoten verknüpft über sein props-Attribut bei der Definition des zugehörigen onClick-Events die übergebene Referenz mit dem Event-Handler der Eltern-Komponente:
import React from ‚react‘;
import './Kind.css'
export default function Kind({
name, artikelnr, preis, bestandteile, funktionEltern,
infoObjekt}
) {
return (
<div>
<h2>{name}</h2>
<h3>{artikelnr}</h3>
<h4>{preis} Euro</h4>
<div>{bestandteile.join(', ')}.</div>
{ // onClick-Event definieren
}
<button onClick={() => funktionEltern(infoObjekt)}>
Nähere Infos </button>
</div>
)
}
Eine React-App besteht grundsätzlich aus einer Hierarchie von Komponenten, die untereinander kommunizieren. Dabei tauschen die Komponenten Daten aus, die sie gegenseitig benötigen. Im Laufe der Zeit gestaltete sich abhängig von der Größe der Hierarchie der Austausch von Daten immer komplizierter. Insbesondere, wenn man die Daten von einer Komponente an eine andere lediglich weiterreichen muss, bis sie das tatsächliche Ziel erreichen. Facebook arbeitete mehrere Jahre an einer Lösung für dieses Problem und veröffentliche erstmals mit der Version 16.3 das offizielle Context-API. Damit verfügt React jetzt über eine effiziente Lösung, die sowohl eine schnelle Kommunikation als auch statische Typprüfung erlaubt.
Neues Context-API vereinfacht Kommunikation der Komponenten
Das Context-API stellt quasi einen globalen Speicherpool für props – den Shared Data Cache – bereit, auf dessen Inhalt in der Hierarchie tieferliegende Komponenten automatisch Zugriff haben. Für diesen Zugriff müssen die betroffenen props überhaupt nicht explizit auf jeder Ebene der Hierarchie deklariert werden. Aufgrund dieses Automatismus spricht man manchmal auch von props-Teleporting. Das Arbeiten mit dem Context-API erfolgt über drei verschiedene Objekt-Konstrukte:Context Definition: die Definition const BeispielContext = React.createContext() definiert ein Context-Objekt mit dem Namen BespielContext; dabei kann man eine Vorbelegung für den Datenwert des Contexts festlegen. Für jeden neuen Context erzeugt React automatisch eine Provider-Komponente ausgehend von deren Klassendeklaration:
import React, { Component } from "react";
// Einen Context erzeugen
const BeispielContext = React.createContext();
class BeispielProvider extends Component {
// Context state einrichten
state = {
daten: { name: "Harald" },
};
// Methode fuer die Aktualisierung des state
setDaten = (daten) => {
this.setState((prevState) => ({ daten }));
};
render() {
// Die Kinder befinden sich in den props
const { children } = this.props;
// Die Daten befinden sich im state
const { daten } = this.state;
/* Die Funktion zur Aktualisierung der
Komponente befindet sich im Provider */
const { setDaten } = this;
return (
{/* Dem Provider Werte und Kind-Komponenten
uebergeben */},
<BeispielContext.Provider
value={{daten, setDaten}}>
{children}
</BeispielContext.Provider>
)
}
}
export default BeispielContext;
export { BeispielProvider };
Context Provider: mit dem Aufruf von <BeispielContext.Provider value= …> in einer Komponente reicht man den auf value folgenden Datenwert an alle eingebetteten Komponenten (die Kinder) weiter. Provider können geschachtelt sein, jede Ebene überschreibt den Datenwert der vorherigen Ebene:
import React from 'react'
import HomePage from './HomePage'
import { BeispielProvider } from './BeispielContext'
function App() {
const daten = { };
return (
<BeispielProvider value={daten.name}>
<HomePage />
</BeispielProvider>
)
}
export default App;
Context Consumer: Weist man einer Komponente MeineKomponente.contextType=BeispielContext einen Context zu, so erreicht man den zugehörigen Datenwert in der Komponente über this.context:
import React, { Component } from 'react'
import BeispielContext from './BeispielContext'
class HomePage extends Component {
static contextType = BeispielContext;
render() {
const { daten, setDaten } = this.context;
return (
<div>
<button
onClick={() => {
const neueDaten = { name: "Otto" };
setDaten(neueDaten);
}}
>
Aktualisiere Daten
</button>
<p>{`Aktuelle Daten: ${daten.name}`}</p>
</div>
);
}
}
export default HomePage;
Durch BeispielContext.Consumer führt React ein Rendern einer Funktion durch, die den Datenwert des Context als Parameter erhalten hat. Sobald der Datenwert eines Providers sich ändert, nimmt React für alle Consumer ein neues Rendering vor.Das Laufzeitsystem von React verwaltet alle React-Komponenten und kontrolliert ihren Lebenszyklus: Ähnlich wie Lebewesen besitzen React-Komponenten verschiedene Phasen quasi von ihrer Geburt bis zum Tod. In jeder dieser Phasen interagiert das React-Laufzeitsystem mit der Komponente und ruft verschiedene Funktionen innerhalb der jeweiligen Phase ihres Lebenszyklus auf. Diese Funktionen im Lebenszyklus einer Komponente bezeichnet man auch als Lifecylce-Hooks oder Lebensyklus-Methoden. Hängt oder fügt man zusätzlichen Code diesen Funktionen einer Komponente hinzu, so kann man deren Verhalten beeinflussen.Zu einem speziellen Lebenszyklus einer Komponente gehören mehrere Funktionen, die React in einer bestimmten Reihenfolge ausführt. Zu den bekanntesten gehören der constructor und die render()-Methode, von denen letztere immer der Programmierer implementiert. Während über den constructor die Daten für status definiert und die props des Elternknoten empfangen werden, dient die render()-Methode dazu, den Inhalt für die HTML-Seite bereitzustellen. Die render()-Methode führt das Laufzeitsystem beim Starten der React-App und immer bei einem Update aus. Mehrere dieser Lebenszyklus-Methoden fasst React zu einer Lebenszyklus-Phase zusammen. Diese Phasen des Lebenszyklus nennt man auch Lifecycle-Events.Die Events kann man einer der folgenden drei Kategorien oder Gruppen zuordnen: Mounting/Hinzufügen-, Updating/Aktualisieren- und Unmounting/Entfernen-Events (Bild 8). Ein Mounting-Event findet statt, wenn ein React-Element als Instanz einer Komponenten-Klasse einem DOM-Knoten hinzugefügt wird. Aktualisiert das React-Laufzeitsystem die Werte von props oder status einer Komponente, so erfolgt dies im Rahmen des Updating-Events. Beim Unmounting-Event entfernt das Laufzeitsystem ein React-Element aus dem DOM. Während die Funktionen des Mounting und Unmounting nur einmalig zur Ausführung kommen, nimmt React über die Lifecycle-Funktionen ein Updating auf Bedarf mittels einer Aktualisierung vor.

Jede Komponente einer React-Appbefindet sich zu einem bestimmten Zeitpunkt in einer vordefinierten Phase ihres Lebenszyklus(Bild 8)
Wojciech Maj
Facebook hat die Reihenfolge und die Implementierung der Lifecycle-Funktionen über die verschiedenen Versionen von React immer wieder verändert. Teilweise wurden auch einzelne Phasen neu konzipiert, zum Beispiel neue Lifecycle-Funktionen hinzugenommen oder vorhandene entfernt. Wichtig ist verstanden zu haben, dass man über diese Funktionen das Verhalten der Komponenten beeinflussen kann. Damit fügt man zusätzliche Logik einer Komponente hinzu, um diese zu verbessern. So lässt sich beispielsweise die Performance zum Lesen von Daten über das Backend erhöhen, wenn dies zum günstigsten Zeitpunkt stattfindet. Auch ergänzende Bibliotheken oder Frameworks bindet man über diese in eine React-App ein.Mit zunehmender Verbreitung von React stellte man fest, dass in manchen Anwendungen für Functional- oder Stateless-Components auch states und Lifecycle-Methoden hilfreich wären. Kann man für eine Functional-Component states definieren, so ermöglicht dies wesentlich mächtigere Handler-Funktionen als wenn es sie nicht gibt. Auch erhält der Entwickler mehr Freiheitsgrade, wenn man für Functional-Components ähnliche Features wie die Lifcecyle-Methoden der Class-Components verfügbar macht. Allerdings wollte Facebook die mit einer Functional-Component verbundenen wesentlichen Vorteile wie ihren wahren Funktionscharakter und den Schutz vor Seiteneffekten innerhalb einer Anwendung gewährleisten.Um dennoch diese Anforderungen ohne Nachteile für Functional-Components zu erfüllen, entschloss sich das React-Team für diese spezielle Funktionen, in der React-Terminologie Hooks genannt, einzuführen. Seit Version 16.8 bietet Facebook in React eine stabile Version der Hooks an. Diese Hooks erlauben einem Programmierer, für eine Functional-Component die benötigten fortschrittlichen Features zu nutzen. Für eine benötigte Funktionalität findet man in der React-Library einen eindeutig zuständigen Hook; damit lassen sich Hooks leicht erweitern und an eigene Bedürfnisse anpassen. Die Erfahrung zeigte, dass man über Hooks Class-Components durch Functional-Components ersetzen kann.
Links zum Thema
<b>◼ <a href="https://reactjs.org/" rel="noopener" target="_blank">Homepage von React</a> <br/></b>