Erhalten Sie Zugang zu diesem und mehr als 300000 Büchern ab EUR 5,99 monatlich.
Das bewährte und umfassende Praxisbuch zu React – jetzt komplett aktualisiert und erweitert! - Vom Einstieg bis zur professionellen React-Anwendung - Lernen mit einem durchgehenden Beispiel - Mit Tipps aus der Entwicklungspraxis der erfahrenen Autoren, z.B. zur Performance-Optimierung - Mit einer Einführung in TypeScript Mit diesem Buch lernst du von Grund auf, wie du mit React professionelle Single-Page-Anwendungen entwickelst. In der Neuauflage ihres bewährten React-Arbeitsbuchs zeigen dir Nils Hartmann und Oliver Zeigermann alles Wesentliche von den Anfängen bis zur produktreifen React-Anwendung. Sie erklären dir dabei, wie du mit TypeScript typsicher und nachhaltig entwickelst und große Anwendungen u.a. mit dem React Context und Redux strukturierst. An vielen Stellen versorgen sie dich zudem mit hilfreichen Tipps aus ihrer eigenen React-Entwicklungspraxis. Unter anderem wirst du folgende Themen kennenlernen: - Anwendungen entwickeln mit der Hooks API und TypeScript - Komponenten gestalten mit CSS - Automatisiertes Testen mit der React Testing Library - Client-Server-Kommunikation mit REST und GraphQL - Navigation im Browser mit dem React Router - Statemanagement mit React Context und Redux - Serverseitiges Rendern von React-Anwendungen - Strategien zur Performance-Optimierung Eigene Kapitel widmen sich den eingesetzten modernen JavaScript-Features sowie TypeScript, sodass zum Verständnis des Buches Kenntnisse von ES5 ausreichen. Neu in der 2. Auflage sind unter anderem: - Die React Hooks API - Testen mit der React Testing Library - Typsichere Anwendungen mit TypeScript - GraphQL-Clients mit React
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 455
Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:
Nils Hartmann ist freiberuflicher Softwareentwickler, -architekt, Trainer und Coach. Er hat langjährige Erfahrung in der Entwicklung mit Java sowie JavaScript/TypeScript, ist Autor von Fachartikeln und unterstützt Teams mit Trainings und Coaching beim Einstieg in JavaScript und die Entwicklung von modernen Webanwendungen. Mehr unter: https://nilshartmann.net
Oliver Zeigermann ist Entwickler, Architekt, Berater und Coach aus Hamburg. Er hat über Jahrzehnte in vielen unterschiedlichen Sprachen und mit vielen Technologien und Ansätzen Software entwickelt. Er ist Autor zahlreicher Fachbücher im JavaScript und React-Bereich, sowie Experte für Machine und Deep Learning. Mehr unter: http://zeigermann.eu/
Zu diesem Buch – sowie zu vielen weiteren dpunkt.büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei dpunkt.plus+:
www.dpunkt.plus
Nils Hartmann · Oliver Zeigermann
Grundlagen, fortgeschrittene Technikenund Praxistipps – mit TypeScript und Redux
2., überarbeitete und erweiterte Auflage
Nils Hartmann, Oliver Zeigermann
Lektorat: René Schönfeldt
Projektkoordinierung/Lektoratsassistenz: Anja Weimer
Copy-Editing: Ursula Zimpfer, Herrenberg
Satz: Gerhard Alfes, mediaservice, Siegen, www.mediaservice.tv
Herstellung: Stefanie Weidner
Umschlaggestaltung: Helmut Kraus, www.exclam.de
Bibliografische Information der Deutschen Nationalbibliothek
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.
ISBN:
978-3-86490-552-0
978-3-96088-419-4
ePub
978-3-96088-420-0
mobi
978-3-96088-421-7
2., überarbeitete und erweiterte Auflage 2020
Copyright © 2020 dpunkt.verlag GmbH
Wieblinger Weg 17
69123 Heidelberg
Hinweis:
Dieses Buch wurde auf PEFC-zertifiziertem Papier aus nachhaltiger Waldwirtschaft gedruckt. Der Umwelt zuliebe verzichten wir zusätzlich auf die Einschweißfolie.
Schreiben Sie uns:
Falls Sie Anregungen, Wünsche und Kommentare haben, lassen Sie es uns wissen: [email protected].
Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.
Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.
Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.
5 4 3 2 1 0
Teil IEinstieg
1Einleitung
1.1Was ist React?
1.2Warum React?
1.3Beziehung zu anderen Technologien
1.4Vergleich mit anderen Webtechnologien
1.5Wie man dieses Buch benutzt
1.6Voraussetzungen für dieses Buch
1.7Änderungen gegenüber der ersten Auflage
1.8Website zum Buch
1.9Danksagungen
2Schnelldurchgang – React im Überblick
2.1Zusammengefasst: Unterschiede zwischen Hooks- und Klassen-API
2.2Ein React-Projekt beginnen mit Create React App
2.3Zusammenfassung
3Die Beispielanwendung: »Vote as a Service«
3.1Die Beispielanwendung installieren und ausführen
3.2Fachliches Modell
3.3Die Anwendung schrittweise entwickeln
3.4Zusammenfassung
Teil IIReact
4Eine React-Komponente
4.1Hands-on: eine Komponente
4.2React-Komponenten in der Übersicht
4.3Hooks
4.4Zustand verwalten mit useState
4.5Ereignisse und Event Handler
4.6JSX zur Beschreibung der UI
4.7Rückgabewerte von Komponenten
4.8Einhängen der Anwendung in den DOM
4.9Arbeiten mit CSS
4.10Zusammenfassung
5Arbeiten mit Komponentenhierarchien
5.1Hands-on: Hierarchien von Komponenten
5.2Kommunikation zwischen Komponenten
5.3Das »Render Properties«-Pattern
5.4Performance-Optimierung: Caching von Werten mit useMemo
5.5Performance-Optimierung: Rendern vom Komponenten unterdrücken
5.6Performance-Optimierung: Code-Splitting mit React.lazy und Suspense
5.7Der React Strict Mode
5.8Zusammenfassung
6Formulare mit React
6.1Hands-on: ein Editor für Umfragen
6.2Hintergrund: Databinding
6.3Controlled Components
6.4Uncontrolled Components
6.5Auf native DOM-Elemente zugreifen: das ref-Property
6.6Komplexen Zustand mit useReducer verwalten
6.7Zusammenfassung
7Arbeiten mit Seiteneffekten: asynchrone Serverzugriffe
7.1Hands-on: Serveranbindung
7.2Seiteneffekte mit useEffect
7.3Code wiederverwenden mit Custom Hooks
7.4Server-Requests mit useState und useReducer
7.5Ausblick: Daten laden mit Suspense
7.6Zusammenfassung
Teil IIIÜber React hinaus
8React-Anwendungen testen
8.1Hands-on: Testen mit Jest und React Testing Library
8.2Überblick: React-Anwendungen testen
8.3React-Test-Bibliotheken
8.4Snapshot Testing
8.5Zusammenfassung
9Der React Router
9.1Hands-on: der React Router im Schnelldurchgang
9.2Anpassungen an der Vote-Anwendung
9.3Links und Routen
9.4Navigation über die History
9.5Authentifizierung
9.6Die React Context API
9.7Lazy Loading mit dem React Router
9.8Testen
9.9Zusammenfassung
10Externes Statemanagement mit Redux
10.1Motivation
10.2Hands-on: eine Redux-Anwendung
10.3Redux in der Vote-Anwendung
10.4Arbeiten mit dem globalen Zustand
10.5Asynchrone Actions
10.6Alternative zu Hooks: die connect-Funktion
10.7Integration von Redux und React Router
10.8Testen von Redux-Anwendungen
10.9Exkurs: Codestruktur von großen React-Anwendungen
10.10Alternative zu Redux: MobX
10.11Zusammenfassung
11React-Anwendungen mit TypeScript
11.1Hands-on: eine React-Anwendung mit TypeScript
11.2TypeScript in React-Anwendungen
11.3React-Komponenten mit TypeScript
11.4Der React Router mit TypeScript
11.5Redux
11.6Zusammenfassung
12GraphQL mit dem Apollo Client für React
12.1Hands-on: ein GraphQL-Client
12.2GraphQL in der Vote-Anwendung
12.3Mutations
12.4Der Apollo Client Cache
12.5GraphQL für externes Statemanagement?
12.6Der Apollo React Client mit TypeScript
12.7Zusammenfassung
Anhang
AServerseitiges Rendern mit React
A.1Ein Beispiel
A.2Gründe für serverseitiges Rendern
A.3Serverseitiges Rendern im Überblick
A.4Herausforderungen
A.5Asynchrones Datenladen mit Redux und dem React Router
BKomponenten als Klassen
B.1React-Komponenten als ES6-Klasse
B.2Methoden-Binding für Event Handler
B.3Zugriff auf native DOM-Elemente
B.4Arbeiten mit Seiteneffekten
B.5Beispiel: Error Boundaries
B.6Klassenkomponenten mit TypeScript
CEinführung in ES.Next
C.1Einleitung
C.2Block-Scope
C.3Template Strings
C.4Destructuring
C.5Klassen
C.6Vererbung
C.7Erweiterte Objekt-Literale
C.8Module, Exporte und Importe
C.9Arrow-Funktionen
C.10Default- und Rest Parameter
C.11Spread-Operator für Arrays
C.12Object.assign und Spread-Operator bei Objekten
C.13Promises
C.14async/await
C.15Generatorfunktionen
C.16Die fetch-API
DEinführung in TypeScript
D.1Motivation
D.2Die Sprache TypeScript
D.3Grundlagen des TypeScript-Typsystems
D.4Externe Typbeschreibungen
EÜbersicht GraphQL
E.1Abfragen
E.2Das Schema: Beschreibung der API
Index
React1 ist eine Open-Source-JavaScript-Bibliothek, mit der du Webanwendungen, sogenannte Single-Page-Anwendungen (kurz SPAs), erstellen kannst. Die Bibliothek wird von Facebook entwickelt und sowohl für facebook.com als auch für Instagram benutzt. Aber auch darüber hinaus ist React sehr weit verbreitet und wird zum Beispiel von Netflix, Airbnb, Twitter oder der Online-Ausgabe des Wall Street Journals verwendet. Da React kaum Bedingungen an seine Umgebung stellt, ist es sehr flexibel einsetzbar. So gibt es auch Webseiten, die React nur für einige interaktive Teile ihres Angebots verwenden.
Single-Page-Anwendungen
Single-Page-Anwendungen (SPAs) zeichnen sich dadurch aus, dass sie vollständig auf dem Client, also im Browser, laufen. Sämtliche Interaktionen werden auf dem Client bearbeitet und die Darstellung der Seite wird mittels JavaScript erzeugt bzw. aktualisiert, um eine möglichst flüssige Darstellung zu erreichen. Mit dem Server werden JavaScript-Code, statische Assets (Bilder, Fonts etc.) und Daten ausgetauscht, aber kein HTML-Code. Zur Entwicklung von Single-Page-Anwendungen haben sich spezialisierte Frameworks und Bibliotheken (in erster Linie React, Angular, Vue oder Web Components) herausgebildet, die von der zugrunde liegenden DOM-API abstrahieren und die Entwicklung dieser Anwendungen vereinfachen.
Im Gegensatz zu SPAs findet bei serverseitig gerenderten Websites und Anwendungen (auch »klassische Webanwendungen« genannt) bei Interaktionen ein Server-Roundtrip statt, bei dem fertiger HTML-Code zurückgeliefert wird. Aus diesem Grund eignet sich dieser Ansatz nur für zumeist statische Websites, auch wenn diese mit JavaScript an einzelnen Stellen um interaktive Features erweitert werden können.
Den Kern von React bilden Komponenten und ihre Komposition zu einer Anwendung. Durch eine solche Komposition wird bestimmt, was dargestellt werden soll oder – aus einer anderen Perspektive – wie man den Zustand einer Anwendung in ihre Darstellung transformiert. Beispiele für den Zustand einer Anwendung können fachliche Dinge sein, wie die Anzahl ungelesener Nachrichten, ein Blogpost, der gerade in der Anwendung bearbeitet wird, oder der zurzeit angemeldete User. Aber auch technische Dinge, wie die Informationen, welches Menü gerade aufgeklappt oder welcher Eintrag in einer Combobox ausgewählt ist, sind Zustand der Anwendung.
Der Kern von React ist übrigens losgelöst vom Web: React kann in unterschiedlichen Szenarien funktionieren, so auch in nativen Anwendungen (zum Beispiel iOS oder Android).
In diesem Buch werden wir uns aber auf die Webentwicklung beschränken und daher auch davon ausgehen, dass du eine Webanwendung mit React bauen willst. Eine solche Anwendung wird früher oder später im DOM des Browsers – der Objektrepräsentation der dargestellten Elemente – gerendert werden. Dazu gibt es zwei Möglichkeiten. In der Regel wird die Anwendung auf Clientseite, also im Browser, gerendert. Du kannst deine Anwendung aber zusätzlich auf dem Server rendern lassen, sofern du dort eine JavaScript-Engine laufen lässt. Dann wird auf dem Server fertiger HTML-Code erzeugt, der zum Browser geschickt wird und dort vom Browser nur noch in den DOM umgewandelt und angezeigt werden muss. Von da an werden alle Updates im Browser gerendert. Das ist sehr praktisch zum Beispiel für eine schnelle erste Anzeige der Anwendung.
React-Anwendungen werden in Komponenten aufgeteilt. Eine Komponente enthält alles Notwendige, um sich darzustellen. Dabei trennt React nicht zwischen Template und Logik; sowohl UI und Logik sind in der Komponente enthalten. Als Ersatz für das Template wird in React der UI-Code direkt in den JavaScript-Code einer Komponente geschrieben. Das geschieht mit der React-eigenen Spracherweiterung JSX, die es ermöglicht, HTML-artigen Code in JavaScript einzubinden.
Ohne an dieser Stelle schon in die Details zu gehen, könnte eine einfache Komponente, die in React als Funktion implementiert werden kann, wie folgt aussehen:
import React from "react";
export default function HelloMessage() {
return <h1>Hello, World</h1>;
}
Wenn diese Komponente in deiner Anwendung verwendet wird, sorgt React dafür, dass ein h1-Element in den DOM eingebaut wird, das den String »Hello, World« beinhaltet.
»UI as a Function«
Du siehst an dieser Stelle ein weiteres, wichtiges Konzept von React: Komponenten werden ausschließlich deklarativ beschrieben. Eine Komponente gibt demnach immer nur genau die UI zurück, die dargestellt werden soll. Man spricht daher von »UI as a Function« in der React-Entwicklung, da – genau wie bei einer mathematischen Funktion – zu demselben Eingabeparameter (React: Zustand) immer derselbe Wert (React: UI) zurückkommt.
Zur Laufzeit kümmert sich React dann darum, dass auch der DOM im Browser entsprechend angepasst wird – und zwar unabhängig davon, wie der DOM zuvor aussah. Die einzelnen Übergänge von einer UI zur nächsten, also das jeweilige Aktualisieren des DOM im Brower, übernimmt React für dich und geht dabei sehr effizient und optimiert vor. Funktionen zum Erzeugen oder Löschen von Elementen (wie beispielsweise createElement oder createAttribute aus der DOM-API) brauchst du in React nicht.
Durch die deklarative Programmierung entfällt eine Menge Komplexität und Fehleranfälligkeit, die aus anderen Ansätzen bekannt sind, da eine wesentliche Fehlerquelle, die diversen Übergänge innerhalb einer Anwendung, nicht implementiert werden müssen. Auch das Testen von Komponenten wird dadurch sehr einfach. In deinem Test übergibst du deiner Komponente ihre Parameter und prüfst hinterher, dass die richtige UI zurückgeliefert wird – genau wie bei einer »normalen« Funktion, nur dass du UI-Elemente überprüfst und keine numerischen oder anderen Werte.
Eigenschaften einer Komponente
Im Folgenden sind die Eigenschaften einer Komponente zusammengefasst:
Komponenten in React repräsentieren einen fachlichen Teil einer Anwendung
. Das kann etwas sehr Einfaches (z.B. ein Eingabefeld) oder auch etwas Komplexes sein (z.B. ein gesamtes Formular). In der Regel werden einfache Komponenten zu komplexeren Komponenten und schließlich zu ganzen Anwendungen aggregiert. Eine Anwendung in React ist technisch genau dasselbe wie eine »einfache« Komponente.
Der Code einer Komponente besteht aus UI und Logik
. Es gibt in React in der Regel keine Trennung nach Techniken wie in anderen UI-Frameworks (z.B. Trennung in Model und View).
Es gibt in React keine Template-Sprache
. Stattdessen wird der UI-Code in JavaScript geschrieben. Um das möglichst einfach zu machen, wird der UI-Code mit der Spracherweiterung JSX geschrieben und sieht dann wie »HTML in JavaScript« aus. Der Tooling-Support (Editoren, IDEs etc.) für JSX ist sehr gut, sodass du trotzdem mit deinem Lieblingseditor (weiter) arbeiten kannst.
Komponenten werden deklarativ beschrieben
. Du gibst in der JSX-Notation immer an, welche UI nach dem Rendern der Komponente im Browser dargestellt werden soll. Dabei brauchst du dich aber nicht darum zu kümmern, wie es zu dieser Darstellung kommt. Unabhängig davon, was vor dem Rendern deiner Komponente im Browser angezeigt wurde, kümmert sich React darum, diese alte Darstellung in die neue, von dir gewünschte Darstellung zu transformieren.
Es gibt in React kein 2-Wege-Databinding zum Abgleich zwischen Model und UI
. Stattdessen aktualisierst du – z.B. nach einer Benutzerinteraktion – den Zustand deiner Komponente und React rendert die komplette Komponente mitsamt ihrer Unterkomponenten neu. Dadurch kann es nie zu Inkonsistenzen in der Darstellung kommen, weil du z.B. vergessen hast, einen Listener (rechtzeitig) an- oder abzumelden. Es wird auch davon gesprochen, dass React die UI als Funktion betrachtet: Abhängig von einem Parameter (dem Model) wird in React immer die gleiche UI zurückgeliefert. Genau wie in einer Funktion, die – sofern sie frei von Seiteneffekten ist – für denselben Parameter immer dasselbe Ergebnis zurückliefert.
Daten in Komponenten sind entweder Properties oder ein interner Zustand
. Properties werden der Komponente von außen, vom Verwender, übergeben. Der Zustand (in React »State« genannt) ist nur komponentenintern und enthält veränderliche Daten, wie z.B. Benutzereingaben. Das Ändern des Zustands führt in React zum erneuten Rendern der gesamten Komponente sowie aller ihrer Unterkomponenten.
Technisch werden Komponenten entweder als Funktion oder als ES6-Klasse geschrieben
. Lange Zeit waren die Klassen der einzige vollwertige Weg, Komponenten zu schreiben. Auch wenn es schon länger möglich war, Komponenten als Funktion zu entwickeln, ist dies erst seit Anfang 2019 (mit der React-Version 16.8) durch die »Hooks-API« eine vollwertige Alternative zu Klassen geworden. Da wir davon ausgehen, dass sich die funktionsbasierte API langfristig durchsetzen wird, werden wir in diesem Buch auch hauptsächlich diese API behandeln. Im Anhang haben wir aber ein Kapitel, das auch die Klassen-API vorstellt. Unabhängig davon, wie du deine Komponenten baust, kannst du innerhalb einer Anwendung Klassen- und Funktionskomponenten beliebig und transparent mischen. Die Frage, Funktions- oder Klassenkomponente, ist nur für die Implementierung der Komponente relevant, aber nicht für deren Verwendung.
In diesem Abschnitt möchten wir dir in aller Kürze Gründe nennen, warum man sich aus unserer Sicht mit React beschäftigen sollte und warum wir glauben, dass React eine sehr gute Bibliothek ist.
Einfachheit:
React hat eine überschaubare API und lässt sich sehr schnell erlernen. Das Architekturmodell hinter React, in dem der Anwendungszustand zentralisiert gehalten wird und die Daten nur in eine Richtung fließen, macht auch große Anwendungen noch gut verständlich und nachvollziehbar.
Kontinuität und Stabilität:
Die Einführung von Änderungen an der React-API erfolgt sehr behutsam. Inkompatible Änderungen werden bereits frühzeitig gut kommuniziert und die Abschaltung von APIs erfolgt erst, wenn es Ersatz dafür gibt. Trotz des relativ konservativen Releasezyklus werden aber beständig neue Features eingebaut. Ein gutes Beispiel dafür ist das derzeit (Stand Ende 2019) aktuelle Major-Release 16 von React, das bereits im September 2017 veröffentlicht wurde2 und jetzt also schon über zwei Jahre (!) aktiv ist. Diese Stabilität bedeutet allerdings nicht, dass keine neuen Features hinzukommen – im Gegenteil! Innerhalb dieses Major-Release sind diverse grundlegende neue Funktionalitäten hinzugekommen, etwa die Hooks-API, die wir in diesem Buch ganz besonders betrachten werden. Diese Änderungen waren allerdings alle abwärtskompatibel, sodass man sie in seiner bestehenden Anwendung einsetzen konnte, aber nicht musste. Du wirst also nicht alle paar Monate oder gar Wochen zu Updates deiner Anwendung gezwungen.
Integrierbarkeit:
React konzentriert sich im Wesentlichen auf die Verwaltung des Zustands deiner Anwendung und insbesondere dessen Darstellung. Dabei macht React nur sehr wenige Annahmen über seine Umgebung, sodass die Bibliothek sich auch sehr gut in bestehenden Projekten und Websites einsetzen lässt und eine sanfte Migration bereits existierender Anwendungen erlaubt. Außerdem kannst du deinen Code so strukturieren, dass UI-unabhängige Logik von React getrennt implementiert wird und somit auch in anderen Projekten mit anderen Technologien weiterverwendet werden kann.
Ökosystem:
Um React herum ist bereits ein sehr lebendiges Ökosystem mit weiteren Tools und Bibliotheken für diverse Einsatzszenarien entstanden. Obwohl React nur ein eine UI-Bibliothek ist, musst du in deinem Projekt also nicht bei »null« anfangen, wenn du z.B. einen Router benötigst. In Teil III dieses Buchs gehen wir auf einige dieser Bibliotheken ein.
Entwicklertools:
Es gibt für React sehr gute Tools zur Entwicklung, nach dem Motto: ohne gute Tools keine guten Anwendungen. Dazu zählen zum Beispiel die React Developer Tools für Chrome und Firefox, ein Kommandozeilen-Werkzeug zum Erzeugen neuer React-Projekte (Create React App) sowie sehr gute Unterstützung in allen populären Editoren und IDEs.
Praxiserprobte Technologie:
React ist sehr weit verbreitet und kommt auf vielen großen und kleinen Websites und Anwendungen im Internet zum Einsatz (neben Facebook zum Beispiel auch bei Netflix, Jira oder Microsoft Outlook) und auch als Lösung für In-House-Anwendungen im Intranet wird React gerne benutzt. Zur Stabilität von React trägt bei, dass neue Features in der Regel zunächst auf der riesigen facebook.com-Codebasis getestet und erst danach als Beta- und dann als finale Version veröffentlicht werden.
React hilft dir, Anwendungen für das Web zu bauen. Dabei ist React selten ganz allein im Einsatz. Insbesondere brauchst du für eine komplette Anwendung zumindest noch:
einen Compiler, der JSX-, modernen JavaScript- und/oder TypeScript-Code nach ES5 übersetzt,
ein Modulsystem zur Strukturierung deiner Anwendung sowie
ein Build-System.
In größeren Anwendungen kommen meistens noch hinzu:
eine architektonische Idee davon, wie eine Anwendung aufgebaut ist,
Routing (Mappen von URLs auf Komponenten für die gewohnte Navigation im Browser) und
ein Type-Checker (z.B. TypeScript).
Die dazu passenden Techniken wollen wir nun kurz beleuchten.
Wie du gesehen hast, brauchen wir zwingend einen Compiler, wenn wir JSX nutzen wollen, denn kein Browser unterstützt den JSX-Code nativ und wird es vermutlich auch nie tun. Zum Übersetzen von JSX ist Babel3 das empfohlene Werkzeug. Babel ist in der Lage, neben JSX die jeweils aktuellen und vielfach auch die kommenden JavaScript-Sprachfeatures, als ES.Next bezeichnet, nach ES5 zurückzuübersetzen, bis diese von allen Browsern unterstützt werden, für die du deine Anwendung zur Verfügung stellen willst.
ES5, ES6, ES.next, ... Historie der JavaScript-Sprachversionen
Wir beziehen uns in diesem Buch auf unterschiedliche Versionen von JavaScript. Unterschiedliche Begriffe können dabei leicht zu Verwirrung führen.
Zuerst zum Unterschied zwischen ECMAScript und JavaScript: ECMAScript ist die Spezifikation der Sprache, die von der Organisation Ecma International veröffentlicht wird. JavaScript ist die Implementierung dieser Spezifikation. In der Praxis spielt dieser Unterschied kaum eine Rolle, und so werden – wenn es um die Benennung einer Version geht – »JavaScript« und »ECMAScript« häufig synonym verwendet.
Von der Spezifikation der Sprache gibt es unterschiedliche Versionen. Bis Juni 2015 war ECMAScript 5 (kurz: ES5) die aktuellste Version, die zu dem Zeitpunkt auch von praktisch allen Browsern unterstützt wurde. Das ist auch der Grund, warum diese Version häufig noch als Zielversion beim Kompilieren verwendet wird (der Internet Explorer 11 zum Beispiel unterstützt weiterhin fast keine neueren JavaScript-Features).
Im Juni 2015 wurde dann der Nachfolger von ES5 veröffentlicht, der häufig als ES6 bezeichnet wird, offiziell aber ECMAScript 2015 heißt. Die Begriffe ECMAScript 6, ES6 und ECMAScript 2015 beziehen sich auf dieselbe Sprachversion. Mit dieser Version gab es sehr viele neue Sprachfeatures (wie Modulsystem, Klassen, Promises, Block Scoping mit let und const, Arrow-Funktionen etc.), sodass man dieses JavaScript auch als »modernes JavaScript« bezeichnet. Die Lern- und Adaptionskurve für dieses Release war und ist dementsprechend hoch.
Aus diesem Grund wird seit 2015 regelmäßig einmal pro Jahr eine neue Sprachversion veröffentlicht (ES5 ist bereits 2009 erschienen), die dafür weniger Features enthält. Diese Versionen werden nach dem Jahr ihres Erscheinens benannt, häufig aber auch noch als ES7, ES8 etc. bezeichnet.
Dazu kommt noch der Begriff ES.Next. Dieser bezeichnet die jeweils kommende, noch unveröffentlichte Version (in Babel kannst du beispielsweise einstellen, dass du ES.Next-Features in deinem Code verwenden und kompilieren möchtest).
Die von uns verwendeten neuen Konzepte ab ES6 haben wir zusammengefasst im Anhang C erläutert. Im React-Umfeld ist es gängig, neue und teilweise auch unveröffentlichte Sprachfeatures recht schnell einzusetzen, was dank Babel auch kein großes Problem ist.
Modul-Loader
Wir strukturieren unsere Anwendung mit ES6-Modulen. Diese und ES6-Imports brauchen aber einen Modul-Loader (auch Bundler genannt), der Abhängigkeiten auflöst, da der Browsersupport für ES6-Imports noch nicht ausreichend ist. Mit Webpack4 und Browserify5 stehen uns hier zwei weitverbreitete Werkzeuge zur Verfügung. Beide lösen ES6-Importe auf und erzeugen je nach Konfiguration eine oder mehrere Ausgabedateien mit allen benötigten Abhängigkeiten. Webpack ist weit verbreitet und kommt auch bei Projekten zum Einsatz, die mit dem offiziellen React-Tool Create React App angelegt wurden.
Code-Splitting
Webpack unterstützt zudem Code-Splitting, das bedeutet, es kann deinen Code im Build in mehrere kleinere Ausgabedateien zerteilen, sodass der Browser initial nicht deine ganze Anwendung laden und interpretieren muss, sondern nur das, was zu einem Zeitpunkt wirklich benötigt wird. Code-Splitting wird auch von React unterstützt; mehr dazu findest du in Kapitel 5.6.
Typensystem für JavaScript
Mit TypeScript6 hat Microsoft eine getypte Erweiterung von JavaScript geschaffen. Du kannst damit für jeden Parameter, jedes Property und jede Variable einen Typ angeben, außerdem kannst du die Struktur von Objekten mit Interfaces beschreiben. Solche Typannotationen haben viele Vorteile. Neben der besseren Lesbarkeit kann dich auch die IDE besser unterstützen. Durch Typannotationen wird auch in der JavaScript-Welt verlässliches Refactoring, Codeanalyse und Code-Completion möglich.
Gerade für größere Projekte, die über einen längeren Zeitraum laufen, halten wir einen Type-Checker für unumgänglich.
TypeScript-Compiler
Microsoft liefert auch gleich einen Compiler mit, der diese Typannotationen checkt und in ES5-Code (oder wahlweise sogar ES3) zurückübersetzt. Der übersetzte Code bleibt dabei lesbar. Da dieser Compiler ebenfalls JSX unterstützt, kannst du den TypeScript-Compiler auch als Alternative zu Babel verwenden.
Man kann diesen Stil der Typannotationen aber auch ohne den TypeScript-Compiler verwenden. Babel ist in der Lage, diese Annotationen herauszufiltern oder per Plug-in auch in der Ausgabe als Kommentar beizubehalten. Als Checker dient dann z.B. die IDE (WebStorm7 und Visual Studio Code8 haben einen sehr guten Support dafür) oder andere Kommandozeilen-Werkzeuge. In Kapitel 11 zeigen wir, wie du TypeScript in deiner React-Anwendung einsetzen kannst.
Ein weiteres Beispiel eines solchen Werkzeugs ist Flow9, das ebenfalls von Facebook entwickelt wird. Flow übersetzt das annotierte JavaScript nicht – das macht ja wie erwähnt bereits Babel –, sondern führt lediglich eine Überprüfung der Typen durch.
Sourcecode formatieren mit Prettier
Prettier10 ist ein Tool zum Formatieren von JavaScript-, TypeScript- und anderem Sourcecode, das in der React-Community eine hohe Verbreitung erfahren hat. Es gibt dafür Integrationen in zahlreiche IDEs und andere Tools. Die Idee hinter Prettier ist, dass unabhängig davon, wer mit welchem Tool den Sourcecode editiert, dieser immer gleich formatiert ist und somit zum Beispiel »überflüssige« Diffs durch unterschiedliche Formatierungen in der Versionsverwaltung vermieden werden.
Auch wenn Prettier nicht dazu gedacht ist, Fehler im Code zu finden, gibt es doch manchmal einen Hinweis darauf, dass sich Syntaxfehler eingeschlichen haben. Wenn der Code beim Speichern nicht automatisch formatiert wird, ist die Wahrscheinlichkeit hoch, dass sich irgendwo ein Syntaxfehler (fehlende Klammer o.Ä.) eingeschlichen hat.
URLs auf Komponenten abbilden
Auch in Single-Page-Anwendungen sollte das Navigieren über die URL des Browsers sowie des Back-Buttons funktionieren. Das Konzept dazu heißt Router: Dieser setzt einerseits die URL in der Navigationszeile des Browsers, sobald ein anderer Anwendungsteils aufgerufen wird. Andererseits kann der Router die zur URL passenden Komponenten ermitteln und rendern lassen.
Der React Router11 ist nur eine von vielen Router-Implementierungen, die mit React benutzt werden können. Allerdings hat er sich als De-facto-Standard etabliert. Daher werden wir dem React Router auch das komplette Kapitel 9 in unserem Buch widmen.
Architekturmodell für React-Anwendungen
Flux12 ist ein von Facebook entwickeltes Architekturmodell, das beschreibt, wie mit React große Anwendungen gebaut werden können. Es definiert dazu ein Anwendungsmodell, bei dem Daten immer nur in eine Richtung durch die Anwendung fließen und dabei einen Kreislauf beschreiben. Das Modell ist weder auf React beschränkt noch ist es Bestandteil von React. Es gibt eine ganze Reihe von Frameworks, die die Flux-Architekturidee ausimplementieren. Die prominenteste Implementierung, die zumindest stark von dieser Idee inspiriert ist, ist Redux (siehe folgenden Abschnitt).
Redux13 ist ein Werkzeug zum »externen Statemanagement«, mit dem du den Zustand deiner Anwendung verwalten kannst, auch wenn diese sehr groß wird. Es ist inspiriert von der Flux-Architektur und bringt eine Reihe von Architekturvorgaben mit. So wird der Zustand der Anwendung an einer einzigen zentralen Stelle gehalten und die Verarbeitung (Logik) geschieht durch pure Funktionen – sogenannte Reducer. Redux stellen wir dir in Kapitel 10 vor.
Das Aufsetzen eines neuen React-Projekts ist aufwendig, da eine ganze Reihe von Tools, insbesondere für den Build, notwendig ist. Das Konfigurieren und Pflegen des Tool-Stacks mit allen Abhängigkeiten kann einen nicht unerheblichen Aufwand auch während der Projektlaufzeit darstellen.
Um dieses Problem zu umgehen, gibt es das Kommandozeilentool Create React App14, mit dem du ein neues Projekt anlegen kannst. In diesem Projekt sind alle wichtigen Abhängigkeiten und das Tooling bereits eingetragen und vorkonfiguriert, sodass du sofort mit der Entwicklung beginnen kannst. Die Konfigurationen der verwendeten Tools (zum Beispiel für den Produktionsbuild), die dann für dein Projekt eingesetzt werden, entsprechen den React-Best-Practices und werden ständig erweitert und verbessert. Du kannst die Versionen der Konfiguration jederzeit in deinem Projekt aktualisieren, um die neuesten Features zu bekommen.
Das Tool Create React App stellen wir dir in Abschnitt 2.2 vor.
Entwickertools für Chrome und Firefox
Für die Entwicklung von React-Anwendungen stehen die React Developer Tools zur Verfügung15. Dabei handelt es sich um eine Erweiterung für die Entwicklertools des Chrome- und Firefox-Browsers.
Die React Developer Tools zeigen in einem eigenen Tab die React-Komponenten einer Webseite sehr übersichtlich mitsamt ihren Properties und des aktuellen Zustands an. Die aktuellen Werte lassen sich darüber ebenfalls verändern, sodass du schnell ausprobieren kannst, wie sich deine Komponente mit anderen Properties verhalten würde.
Abb. 1–1Die React Developer Tools
Neben React gibt es eine ganze Reihe weiterer Webtechnologien. Manche dieser Techniken sind ergänzend und andere wiederum für denselben Einsatzzweck gedacht und stellen damit eine Konkurrenz dar. Ein Vergleich kann für eine Einordnung spannend sein und dir beim Einstieg helfen, wenn du bereits Erfahrungen mit einer der folgenden Techniken hast.
Web Components
Web Components sind der Standard für eine ganze Reihe von Techniken sein16. Jede dieser Techniken kann man in Kombination mit den anderen oder für sich allein verwenden.
Custom Elements17 erlauben die Definition von eigenen HTML-Tags inklusive lokalem CSS und JavaScript. Du kannst also sowohl Aussehen als auch Verhalten für ein solches neues HTML-Tag definieren.
Shadow DOM
Über das sogenannte Shadow DOM18, in dem sich die Komponente darstellt, wird die Lokalität der Komponente realisiert.
HTML Templates19 lassen dich HTML in die Seite einbinden, ohne dass es unmittelbar auf der Seite dargestellt wird. Dies kann nützlich sein, um das Template später durch ein Skript mit Werten zu versehen und im Browser-DOM darzustellen. Obwohl diese Erweiterung als Teil von Web Components begonnen hat, wird sie nun als Teil der HTML-Spezifikation weiterentwickelt.
Die Programmierung von Web Components erfolgt imperativ und mit Listenern. Die Bibliothek Lit Elements20 stellt für Web Components ein deklaratives Programmiermodell zur Verfügung, das vom Konzept an React erinnert.
Verwendung von Web Components in React-Komponenten
Web Components können wie jedes andere HTML-Element in einer React-Komponente genutzt werden. Diese Möglichkeit war eine bewusste Entscheidung der React-Entwickler. Hier sperrt man sich also nicht gegen Web Components, auch wenn es bei der Integration einige technische Schwierigkeiten gibt21.
Andere wiederum sehen in React eher eine Konkurrenz zu Web Components, sind aber mit React nicht zufrieden, weil es kein Standard ist. Laut der Aussage eines React-Kern-Entwicklers wird sich React nicht an Web Components annähern, allerdings auch nicht den Gebrauch zusammen mit React ausschließen, sondern ihn so weit wie möglich unterstützen22.
Der Hype »vor React«
Angular kommt in zwei unterschiedlichen Versionen daher, die mehr oder weniger unterschiedlich und inkompatibel sind. Angular 123 (»AngularJS«) gibt es schon sehr lange und man kann es ohne Wenn und Aber den »Hype vor React« nennen. Angular in der Version 2 hat mit einer ganzen Reihe von Konzepten aus Angular 1 gebrochen. Die Versionen ab Angular 2 werden deswegen auch »Angular« genannt (im Gegensatz zu »AngularJS«, was sich auf Version 1 bezieht).
Sowohl AngularJS als auch Angular sind jeweils ein komplettes Framework, inklusive Router und klaren Vorstellungen von einer Architektur und der Art und Weise, wie getestet wird. So gibt es neben Komponenten zum Beispiel ein Modulkonzept, Services und Dependency Injection. Angular ist mit TypeScript entwickelt und auch Angular-Anwendungen werden darin geschrieben.
Vue24 ist ebenfalls ein komponentenbasiertes JavaScript-Framework zur Entwicklung von Single-Page-Anwendungen. Im Gegensatz zu React kommen hier viele Bausteine mit, etwa ein Router und eine offiziell unterstützte Redux-Version für das Zustandsmanagement.
Vue verwendet genau wie Angular eine Template-Sprache, hat aber eine schlankere API und macht weniger Vorgaben, wie die Anwendung strukturiert sein soll. Das Framework wurde 2014 veröffentlicht, wird von einer Open-Source-Community entwickelt und hat sehr schnell eine große Verbreitung gefunden. Die Version 3 von Vue wird genau wie Angular in TypeScript entwickelt.
Native Anwendungen mit React Native
React Native bietet eine Möglichkeit, mit React native Komponenten nicht nur für das Web, sondern auch für andere Systeme (unter anderem Android und iOS) zu entwickeln. Dabei wird eine andere Version des virtuellen DOM verwendet, die eine React-Komponente nicht für den DOM aufbereitet, sondern auf native Komponenten des Betriebssystems abbildet. Als JavaScript-Engine kommt sowohl bei Android als auch bei iOS Webkits JavaScript-Engine JavaScriptCore25 zum Einsatz.
Die in diesem Buch behandelten Themen sind komplex und umfangreich, zudem befinden sie sich in vielen Teilen im Fluss. Alle Themen auf dem neuesten Stand in einem Buch zu behandeln, ist daher nicht möglich. Stattdessen nehmen wir dich als Leser an die Hand und führen dich an die zentralen Themen der React-Welt heran. Für einige Details und weiterführende Informationen verweisen wir mithilfe von Links auf die aktuellsten Quellen im Internet.
Die Teile des Buchs
Das Buch gliedert sich in drei Teile.
Im ersten Teil geben wir dir einen kurzen Überblick darüber, was React überhaupt ist. Dazu führen wir im folgenden Kapitel zunächst ein sehr kleines Beispiel ein, damit du einmal kompakt sehen kannst, wie React sich »anfühlt«. Für den weiteren Verlauf des Buchs entwickeln wir dann eine größere Anwendung, die wir dir ebenfalls in diesem Teil vorstellen.
Im zweiten Teil leiten wir die grundlegenden Konzepte von React her. Wir sehen uns an, wie Komponenten entwickelt werden, welche Eigenschaften und Funktionen Komponenten haben und wie diese zusammenspielen. Außerdem werfen wir einen Blick darauf, welche Besonderheiten es gibt, wenn mit React Benutzereingaben, z.B. in Formularen, verarbeitet werden sollen und wie du Daten über eine REST API lesen und schreiben kannst.
Im dritten Teil blicken wir über den Tellerrand hinaus und sehen uns das Ökosystem von React an, also Technologien und Bibliotheken, die häufig in React-Projekten zum Einsatz kommen, aber nicht Bestandteil von React selbst sind. Neben der Frage, wie du React-Anwendungen testen kannst, gehören dazu die Bibliotheken Redux, React Router, GraphQL und die Sprache TypeScript.
Am Schluss folgt noch der Anhang. Hier geben wir dir einen Überblick, wie du deine React-Anwendung serverseitig rendern kannst. Außerdem werfen wir einen Blick auf die Klassen API von React und geben dir eine Einführung in TypeScript, in neuere JavaScript-Features, die für React wichtig sind, sowie in die Abfragesprache GraphQL.
Hands-on-Abschnitte
Jedes Kapitel in Teil II und III beginnt mit einem Hands-on-Abschnitt. In diesem werden anhand eines praktischen Beispiels die wichtigsten Konzepte des Kapitels erläutert. In den weiteren Teilen des Kapitels wird dann je nach Schwerpunkt des Kapitels die Anwendung weiterentwickelt und/oder auf weitere Details eingegangen.
Auch wenn du die in den Hands-on-Teilen beschriebenen Schritte nicht selber nachprogrammierst, kannst du damit einen praktischen Überblick über das vorgestellte Thema bekommen. Daher haben wir in den Teilen auch relativ viel Code abgedruckt, damit du zum Nachvollziehen nicht vor dem Computer sitzen musst.
Die Kapitel des Buchs bauen aufeinander auf. Ab Kapitel 4 verwenden wir durchgehend unsere Beispielanwendung, um die Konzepte von React zu demonstrieren. Insbesondere im dritten Teil sind die vorgestellten Technologien und Bibliotheken teilweise so komplex, dass wir sie am Anfang des Kapitels im Hands-on-Teil an einem kleinen, separaten Beispiel zeigen. Im Laufe des Kapitels beschreiben wir dann in Ausschnitten, wie sich die jeweilige Technologie auf unsere Anwendung auswirkt.
ES5-Kenntnisse notwendig
Wir verwenden in diesem Buch konsequent die JavaScript-Versionen ECMAScript 2015 und neuer (ES.Next). Es genügt aber, wenn du mit der vorangegangenen Version ES5 vertraut bist. Die wichtigsten von uns verwendeten Neuerungen der Sprache haben wir im Anhang zusammengestellt, sodass du dort bei Bedarf nachschlagen kannst.
HTML und DOM
Neben ES5 solltest du außerdem HTML und das Document Object Model (DOM) kennen.
npm
Wenn du die Beispiele ausprobieren möchtest, muss auf deinem Rechner der Node Package Manager npm installiert sein. Mit npm werden wir die Module (Frameworks und Bibliotheken) für unsere Anwendung installieren und die Anwendung auch starten. Achtung: Die Beispiele sind mit npm in der Version 6.9.x getestet!
Node.js
Für den serverseitigen Beispielcode verwenden wir Node.js. Wenn du diese Teile ausprobieren möchtest, brauchst du eine Node.js-Installation auf deinem Rechner. (Wir haben mit Version 10.16.x getestet.)
Die zweite Auflage wurde komplett überarbeitet und stellt jetzt die Hooks-API in den Vordergrund. Wir zeigen die wichtigsten React Hooks sowie die Hooks-API von React Router, Redux und GraphQL.
Neu hinzugekommen sind außerdem Beschreibungen diverser React-APIs, wie Suspense, Caching oder Code-Splitting, Tests mit der React Testing Library und das Tool Create React App. Außerdem betrachten wir die Entwicklung von React-Anwendungen mit TypeScript. Als Grundlage dafür gibt es im Anhang eine Einführung in die Sprache TypeScript.
Wir haben zu diesem Buch eine Website eingerichtet, über die du unter anderem zu unserem GitHub-Repository mit dem Beispielcode findest. Auf der Seite werden wir aber auch Korrekturen und Ergänzungen zum Buch und zu den Beispielen veröffentlichen, insbesondere auch zu Neuerungen in React. Die Adresse der Seite lautet:
https://reactbuch.de
Anregungen, Kommentare und Fragen nehmen wir jederzeit gerne entgegen. Du kannst uns erreichen unter der E-Mail-Adresse:
oder über Twitter:
Nils Hartmann @nilshartmann
Oliver Zeigermann @DJCordhose
Alternativ kannst du uns auch im GitHub-Repository der Beispielanwendung gerne einen Issue einstellen (https://github.com/react-buch/vote-example-v2/issues).
Bei der Erstellung dieses Buchs haben uns eine ganze Reihe von Menschen geholfen, denen wir ganz herzlich danken wollen!
Unser Dank gilt dabei auch denjenigen, die das Buch schon vor der Fertigstellung gelesen und kommentiert haben und die auch für diese zweite Auflage sehr gutes Feedback gegeben haben.
Darüber hinaus möchten wir uns ganz herzlich beim Team vom dpunkt.verlag und allen an der Produktion Beteiligten bedanken, die uns nach Kräften geholfen und mit Rat und Tat zur Seite gestanden haben.
Bevor wir in die Details von React gehen, möchten wir dir in diesem Kapitel die wichtigsten Features von React im Schnelldurchgang an einem sehr einfachen Beispiel zeigen. Das Beispiel kannst du auf der Plattform CodeSandbox, die Online-Editoren für JavaScript anbietet, nachvollziehen, ohne dass du dafür etwas bei dir lokal auf deinem Computer installieren musst. (CodeSandbox selbst ist übrigens auch mit React gebaut.)
Um das Beispiel zu entwickeln, kannst du in CodeSandbox ein neues React-Projekt anlegen. Dazu öffnest du https://codesandbox.io/, klickst auf »Create Sandbox« und wählst dann unter »Popular Templates« »React« aus. Daraufhin wird ein Projekt angelegt, in dem die Abhängigkeiten auf die React-npm-Module bereits hinzugefügt sind und einige weitere Dateien angelegt sind.
Je nach Einstellung findest du auf der linken Seite einen Explorer mit allen Dateien des Projekts, in der Mitte einen Editor (der sich wie VS Code verwenden lässt!) und rechts die Darstellung deiner Anwendung in einem simulierten Browser. Sobald du den Code deiner Anwendung veränderst, wird die Anwendung übersetzt (z.B. JSX nach ES5) und die Darstellung im simulierten Browser automatisch aktualisiert.
Für diesen Schnelleinstieg wollen wir eine ganz einfache Hello-World-Anwendung bauen, die nur aus einer einzigen Komponente besteht. Komponenten sind das zentrale Element in React und wie wir später noch sehen werden, sind Anwendungen in React nichts weiter als eine Menge von Komponenten.
Abb. 2–1Der Online-Editor CodeSandbox mit Datei-Explorer, Editor und Vorschau der Anwendung
Die Komponente unserer Anwendung, Greeter, besteht aus einem Eingabefeld, in dem ein Gruß eingegeben werden kann. Der eingegebene Gruß darf eine bestimmte Länge nicht überschreiten. Die Anzahl der verbleibenden Zeichen steht unterhalb des Eingabefeldes. Außerdem gibt es einen Knopf, der den aktuellen Gruß ausgibt. Aktiv ist der Knopf allerdings nur, wenn der Gruß »gültig« ist, das bedeutet, er enthält mindestens ein Zeichen und die Länge ist kleiner oder gleich der erlaubten Maximallänge.
Beispiel: die Greeter-Komponente
Der erste Schritt unserer Anwendung sieht wie folgt aus, du kannst diesen Code so, wie er da steht, in die index.js-Datei deiner Sandbox einsetzen:
Sehen wir uns den Code der Komponente Schritt für Schritt an. Eine Komponente in React ist eine JavaScript-Funktion. In dieser Komponentenfunktion ist alles enthalten, was die Komponente benötigt, um sich darstellen zu können: sowohl die Logik als auch die UI.
Beschreibung der UI mit JSX
Die UI, die unsere Komponente darstellen soll, findest du im return-Statement der Komponente. Dort haben wir mit einer HTML-artigen Syntax die Elemente beschrieben, die zur Laufzeit im Browser dargestellt werden sollen. Dieser HTML-artige Code, JSX genannt, wird zur Build-Zeit von einem Compiler (Babel oder TypeScript) in gültiges JavaScript übersetzt. Für uns hat dieser Ansatz den Vorteil, dass wir keine Template-Sprache lernen und verwenden müssen (auch wenn dieses Vorgehen am Anfang sicherlich gewöhnungsbedürftig und vielleicht sogar abschreckend sein mag).
Variablen verwenden
Innerhalb des JSX-Codes können wir auf JavaScript-Variablen und -Funktionen zugreifen. Im Button, der den Gruß anzeigen soll, geben wir damit an, ob der Button aktiv oder inaktiv sein soll. Außerdem geben wir eine Callback-Funktion an, die ausgeführt werden soll, sobald auf den Button geklickt wird. Diese Eigenschaften eines Elementes werden in React Properties genannt. Sowohl disabled als auch onClick sind somit Properties des Button-Elements, genauso wie value und onChange Properties des input-Felds sind.
Properties
Auch unsere Komponente selbst nimmt ein Property entgegen, mit dem der Verwender der Komponente angeben kann, wie lang der Gruß maximal sein kann (maxLength). Properties werden einer Komponente über das erste Funktionsargument, props, in einem Objekt übergeben, sodass wir in unserem Beispiel auf das einzige Property der Komponente mit dem Ausdruck props.maxLength zugreifen können und die Anzahl verbleibender Zeichen sowie das Enablement des Buttons berechnen können.
An dem input-Element geben wir mit dem onChange-Property eine Callback-Funktion an, die aufgerufen wird, wenn sich das input-Feld zur Laufzeit ändert, also beispielsweise, weil ein Zeichen eingegeben wurde. Da React über keine Möglichkeit verfügt, Daten aus der UI automatisch an ein Model zu binden (2-Wege-Databinding), müssen wir uns selber darum kümmern.
State
Das Model einer Komponente wird in React Zustand oder State genannt und wird mit der Funktion React.useState erzeugt, der wir als Parameter einen initialen Wert für den Zustand übergeben (in unserem Beispiel einen Leerstring). Diese Funktion liefert uns ein Array mit zwei Einträgen zurück: den aktuellen Wert des Models (in unserem Fall der String mit dem Gruß) und eine Setter-Funktion zum Ändern des Models.
Ändern des Zustands löst Rendern aus
Das Besondere an dem Zustand ist: Sobald wir diesen mit der zurückgelieferten Setter-Funktion ändern, wird die gesamte Komponentenfunktion von React erneut aufgerufen und ausgeführt, sodass sie ihre aktualisierte UI zurückliefern kann.
Da wir die Setter-Funktion als Reaktion auf Änderungen im Eingabefeld aufrufen, wird die Komponentenfunktion folglich nach jeder Veränderung im Eingabefeld neu aufgerufen. Bei diesen folgenden Aufrufen der Greeter-Funktion liefert useState nun jeweils den aktualisierten Wert des Models zurück (und nicht mehr den initialen Wert), den React für uns im Hintergrund verwaltet und aufbewahrt.
Innerhalb unserer Funktion können wir abhängig vom Zustand nun eine komplett neue UI beschreiben. Dabei übernehmen wir zum Beispiel den Wert (aktueller Gruß) in das input-Feld (value-Property) und setzen das Enablement des Buttons neu. Auch die Anzeige der verbleibenden Zeichen für den Gruß wird aktualisiert.
Deklarative UI
Eine Stärke dieses Vorgehens, der deklarativen Beschreibung der UI und des erneuten Ausführens der kompletten Funktion nach einer einzelnen Änderung, ist es, dass wir nicht in inkonsistente Zustände in der UI kommen können. Alle UI-Elemente, die den Zustand oder Teile davon oder davon abgeleitete Werte (Anzahl verbleibender Zeichen) anzeigen, werden in jedem Fall vollständig aktualisiert.
Nach dem Ausführen der Funktion aktualisiert React anhand der zurückgelieferten UI die Darstellung im Browser. Und obwohl wir immer die komplette UI der Komponente an React zurückgeben, nimmt React nur so wenige Änderungen im DOM wie nötig vor, damit dort die Änderungen so schnell und so effizient wie möglich erfolgen.
Abb. 2–2Die Hello-World-Anwendung
ReactDOM.render
Beim Starten unserer Anwendung müssen wir React nun noch angeben, dass unsere Komponente überhaupt dargestellt werden soll. Dazu verwenden wir die Funktion ReactDOM.render. Dieser Funktion übergeben wir unsere Greeter-Komponente, ebenfalls in der JSX-Notation, wie oben schon bei button, input etc. gesehen. Dabei geben wir auch das Property maxLength an. Außerdem erwartet die Funktion als zweiten Parameter einen DOM-Knoten aus der aktuellen Seite, unterhalb dessen die Komponente dargestellt werden soll. In unserem Beispiel ist dieser DOM-Knoten ein div-Element mit der Id root, den du in der erzeugten index.html-Datei im public-Ordner der Sandbox findest.
Rendern
Zum Rendern der Komponente füge nun bitte den Import für ReactDOM und den entsprechenden render-Aufruf in der index.js-Datei hinzu:
import React from "react";
import ReactDOM from "react-dom";
export default function Greeter(props) {
...
}
ReactDOM.render(<Greeter maxLength={20} />,
document.getElementById("root")
);
Nun wird die Komponente im Browser von CodeSandbox angezeigt und du kannst sie direkt dort ausprobieren. Eine Sandbox mit der fertigen Beispielanwendung findest du unter https://codesandbox.io/s/react-buch-schnell-01-0fpvp.
In diesem Buch verwenden wir fast ausschließlich die Hooks-API, die erstmals Ende 2018 vorgestellt und im Februar 2019 mit React 16.8 in einer stabilen Version veröffentlicht wurde.
Hooks sind Funktionen, mit denen du nahezu alle React-Features in Funktionskomponenten verwenden kannst, die zuvor der Klassen-API vorbehalten waren (zum Beispiel Arbeiten mit State). Falls du schon die Klassen-API, zum Beispiel aus der ersten Auflage dieses Buchs, kennst, geben wir dir hier zur groben Orientierung eine kurze Gegenüberstellung zwischen Klassen- und Hooks-API:
Zustand/State einer Komponente: Dafür ist der
useState
-Hook (siehe
Kapitel 4
) zuständig. Das State-Objekt gibt es in Funktionskomponenten nicht, für einen komplexeren Zustand kannst du den
useReducer
-Hook verwenden (siehe
Kapitel 6
).
Die Lifecycle-Methoden aus den Klassenkomponenten haben kein direktes Pendant in der Hooks-API. Stattdessen verwendest du den
useEffect
-Hook (siehe
Kapitel 7
).
Die Funktionalität von Pure Components sowie der
shouldComponentUpdate
-Methode können durch den
useMemo
-Hook umgesetzt werden (siehe
Abschnitt 5.4
).
Als Ersatz für die Verwendung der Provider-Komponente, um auf React Context zuzugreifen, gibt es den
useContext
-Hook (siehe
Abschnitt 9.6
).
Higher-Order Components (HOCs) gibt es weiterhin, allerdings gibt es mit der Möglichkeit, eigene Hooks zu bauen, eine API, die möglicherweise einfacher und besser zu verstehen ist. Möglicherweise werden HOCs deswegen künftig seltener eingesetzt werden.
Die Aufgaben der
connect
-Funktion von Redux können durch die Hooks
useSelector
und
useDispatch
übernommen werden (siehe
Kapitel 10
).
Die
withRouter
-HOC aus dem React-Router-Projekt sowie die
render
- und
component
-Properties der
Route
-Komponente werden durch diverse neue Hooks ersetzt (siehe
Kapitel 9
).
Um die Auswirkungen auf den Code einer React-Anwendung zu sehen, haben wir die fertige Beispielanwendung im Repository auch in einer Variante mit der Klassen-API abgelegt. So kannst du React-Code mit Klassen- und Hooks-API vergleichen.
Um ein ernsthaftes React-Projekt zu beginnen und zu entwickeln ist eine ganze Reihe an Infrastrukturkomponenten erforderlich:
Neuerer JavaScript-Code, der (noch) nicht von allen Browsern verstanden wird, muss in eine ältere JavaScript-Sprachversion zurückübersetzt werden, die von allen Browsern, auf denen deine Anwendung laufen soll, unterstützt wird. Das ist in der Regel ES5. Zudem muss der React-proprietäre JSX-Code (siehe
Kapitel 4
) in gültiges und verständliches JavaScript übersetzt werden. Zum Kompilieren des Sourcecodes wird in der Regel Babel oder TypeScript verwendet.
Auch für die Arbeit mit JavaScript-Modulen wird ein Tooling benötigt. Zum einen verstehen nicht alle Browser das native JavaScript-Modulsystem, das 2015 eingeführt wurde. Zum anderen gibt es weitere Modulsysteme, in denen Module vorliegen können, die du möglicherweise in deiner Anwendung verwendet möchtest. Ein populäres Modulsystem ist das aus NodeJS stammende Require-JS, für das es eine Reihe von Modulen gibt, die auch im Browser laufen und die du bei Bedarf in deiner Anwendung verwenden kannst. Um deine eigenen und die von dir verwendeten Module für den Browser aufzubereiten, wird ein Bundler benötigt. Während ein Compiler sich um das Übersetzen eines Moduls von einer JavaScript-Sprachversion in eine ältere kümmert, sorgt der Bundler dafür, dass deine Module, unabhängig davon welches Modulsystem du verwendest, auch im Browser funktionieren. Eines der prominentesten Bundler ist Webpack.
Für das Testen deiner Anwendung benötigst du ein Testbibliothek, das in der Lage ist, React-Komponenten zu testen. Die Tests sollen natürlich regelmäßig – zum Beispiel im CI-Build – ausgeführt werden.
Während du deine Anwendung entwickelst, benötigst du einen Webserver, über den du deine Anwendung testweise betreiben kannst. Darüber sollten Änderungen, die du vornimmst, auch sofort im Browser sichtbar werden, ohne dass du viel Mühe damit hättest. Du benötigst also Werkzeuge für die Automatisierung. Hier kommt der Webpack Development Server ins Spiel, der dafür sorgt, dass bei Änderungen an deinem Sourcecode die Anwendung neu kompiliert und im Browser aktualisiert wird.
Neben der Konfiguration dieser Tools für den Entwicklungsprozess benötigt man in der Regel auch eine spezialisierte Konfiguration für das Bauen einer Anwendung, die dann auch in Produktion ausgeliefert wird. Während bei der Entwicklung eher die Build-Dauer und der Entwicklungskomfort, etwa zum Debuggen, im Vordergrund stehen, ist beim Bauen der Anwendung für die Produktion eher entscheidend, dass die fertigen Artefakte zum Beispiel möglichst klein werden.
Das Einrichten eines Projekts mit all den benötigten Tools sowie das manuelle Pflegen ihrer unterschiedlichen Versionen und Konfigurationen kann sehr zeitaufwendig sein. Aus diesem Grund gibt es das Projekt Create React App1, das dir diese Aufgaben abnimmt. Mit Create React App kannst du ein neues React-Projekt erzeugen lassen. Das Projekt enthält dann fertige und sehr ausgereifte Konfigurationen für Babel (auf Wunsch TypeScript) und Webpack. Auch Unterstützung für CSS ist enthalten und es werden für alle Artefakte SourceMaps erzeugt, sodass du trotz proprietärem JSX-Code weiterhin zum Beispiel im Browser debuggen kannst (siehe Abb. 2–3). Darüber hinaus enthält das generierte Projekt Konfigurationen für einen Produktionsbuild, der nach den jeweils gültigen Best Practices implementiert ist und sehr gute Ergebnisse erzielt.
Abb. 2–3Debuggen einer React-Komponente in Chrome
Um ein neues Projekt zu starten, kannst du mit dem Tool npx (Bestandteil von npm) create-react-app ausführen. Dazu öffnest du eine Kommandozeile und gehst in das Verzeichnis, in dem das neue Projekt (in einem neuen Verzeichnis) angelegt werden soll:
npx create-react-app PROJEKT_NAME
Mit diesem Aufruf erstellt Create React App ein neues Verzeichnis und legt darin die package.json-Datei mit den notwendigen Abhängigkeiten an. Außerdem werden schon einige beispielhafte Source-Dateien angelegt, sodass du gleich mit dem Entwickeln anfangen kannst.
ESLint
Bestandteil des erzeugten Projekts ist auch die Konfiguration von ESLint2, einem populären Linter für JavaScript. Ein Linter ist ein Tool zur statischen Codeanalyse, das Probleme im Sourcecode aufdecken kann (z.B. Verwendung nicht deklarierter Variablen und ungenutzte Variablen). ESLint lässt sich mit Regeln beliebig konfigurieren und es gibt auch fertige Regeln für die Entwicklung von React-Anwendungen. Einige Regeln sind in dem mit Create React App erzeugten Projekt bereits eingetragen, sodass du bei typischen Codeproblemen Hinweise darauf beim Build bekommst. Viele IDEs und Editoren (z.B. VS Code oder Webstorm) zeigen dir die Hinweise auch direkt beim Bearbeiten einer Datei an.
Abb. 2–4Darstellung von Problemen aus ESLint in Visual Studio Code
Auch unsere Beispielanwendung haben wir initial mit Create React App erzeugt und nur die generierten Source-Artefakte gelöscht bzw. für unsere Zwecke angepasst.
Wenn du ein Projekt mit Create React App erstellst, ist der dabei erzeugte Code bereits für die Entwicklung einer Progressive Web App3 (PWA) ausgelegt. Progressive Web Apps sind Webanwendungen, die über Features verfügen, die in der Vergangenheit nativen Anwendungen vorbehalten waren. Dazu gehört zum Beispiel die Möglichkeit, die Anwendung auf dem Homescreen eines Mobilgerätes installieren zu können. Dazu muss die Anwendung eine Manifestdatei enthalten, die zum Beispiel darüber Auskunft gibt, welchen Titel die Anwendung anzeigen und welches Icon sie verwenden soll. PWAs sind außerdem auch offline-fähig, sodass sie auch geöffnet und verwendet werden können, wenn keine Netzverbindung besteht. Dazu werden Service Worker4 verwendet, die Daten cachen können.
Beide Artefakte, das Manifest und ein Service Worker, werden von Create React App automatisch erzeugt. Der generierte Service Worker ist aber per Default nicht aktiviert, da Entwicklung und Betrieb von Anwendungen mit einem Service Worker nicht unproblematisch ist. Du kannst den Service Worker aber in der generierten index.js-Datei jederzeit einschalten.
Damit hast du eine gute Basis, um deine React-Anwendung bei Bedarf als Progressive Web App zu bauen.
Eine Besonderheit von Create React App bzw. den Projekten, die mit Create React App erzeugt wurden, ist, dass es die Abhängigkeiten auf die Tools (Babel, Webpack etc.) nicht direkt in deine package.json-Datei einträgt. Stattdessen wird ein Verweis auf ein Modul mit dem Namen react-scripts eingetragen. Dieses Modul wiederum enthält dann sämtliche Konfigurationen und bestimmt, welche Tools in welcher Version zum Einsatz kommen. Das Modul wird von dem Team gepflegt, das Create React App entwickelt. Gibt es neue Versionen der abhängigen Tools, zum Beispiel eine neue Webpack-Version, oder Verbesserungen in der Konfiguration, zum Beispiel eine Optimierung für den Build-Prozess, wird react-scripts von den Entwicklern angepasst und eine neue Version veröffentlicht. Du kannst dann von den Neuerungen auch in deinem bestehenden Projekt profitieren, indem du dort einfach die Version von react-scripts in deiner package.json-Datei anpasst.
Anpassen der Konfiguration
Die Kehrseite der Medaille ist, dass du von der Konfiguration weitgehend abgeschnitten bist. Bis auf wenige Parameter kannst du die Konfiguration nicht beeinflussen. Zwar ist die Konfiguration sehr gut und für viele Einsatzzwecke auch völlig ausreichend, aber natürlich kann es immer vorkommen, dass du doch an der Konfiguration arbeiten musst. Für diesen Fall gibt es zwei Möglichkeiten: Zum einen kannst du das Projekt react-scripts auf GitHub klonen, anpassen und eine eigene Variante für dein Projekt davon erzeugen, die du dann in die package.json-Datei einträgst. Sofern du später feststellst, dass – z.B. durch eine neuere Version – react-scripts doch wieder für dich ausreichend ist, kannst du wieder auf react-scripts umstellen.
»Auswerfen« von react-scripts
Falls dieser Ansatz für dich nicht ausreichend ist, kannst du das Projekt react-scripts »auswerfen« lassen. Dieses Verfahren heißt in Create React App »eject«. Damit werden alle Konfigurationen und Abhängigkeitsbeschreibungen direkt in dein Projektverzeichnis kopiert und die Abhängigkeit auf react-scripts entfernt. Dein Projekt sieht dann so aus, als ob dort direkt (wie in einem »traditionellen« Projekt) die Konfigurationen und Abhängigkeiten eingetragen worden wären, sodass du dort beliebig Anpassungen machen kannst. Der Nachteil dieses Ansatzes ist, wenn du einmal »ausgeworfen« hast, kommst du nicht mehr zurück. Du bist dann von den Neuerungen in react-scripts abgeschnitten.
React-Anwendungen bestehen aus HTML-, JavaScript- und CSS-Dateien. Dazu kommen unter Umständen weitere statische Assets wie Bilder oder Fonts.
Wenn du dein Projekt mit Create React App erzeugt hast, kannst du mit dem npm-Script build dir eine fertige Anwendung bauen lassen, die für den produktiven Einsatz optimiert ist, unter anderem sind JavaScript- und CSS-Code minifiziert und unter Umständen auch auf mehrere Dateien aufgeteilt:
npm run build
Die erzeugen Dateien werden in das build-Verzeichnis geschrieben. Zum Veröffentlichen deiner Anwendung über einen Webserver musst du dieses Verzeichnis auf deinen Webserver kopieren und ihn als Web-Root für den gewünschten Server, die Domain oder den Pfad festlegen.
In diesem Kapitel haben wir uns anhand einer sehr einfachen Beispielanwendung die grundlegenden Konzepte von React im Code angesehen.
Komponenten in React werden als Funktionen geschrieben, die von außen Parameter (Properties) bekommen und intern einen Zustand halten. Die Komponente ist verantwortlich, dafür eine UI zu erzeugen.
Mit dem Online-Editor CodeSandbox kannst du ohne etwas installieren zu müssen, React ausprobieren. Den Editor kannst du auch gut benutzen, um mit anderen über Code zu diskutieren (zum Beispiel für Bug-Reports).
»Echte« React-Projekte kannst du mit Create React App automatisiert anlegen. Projekte, die damit begonnen werden, verfügen über eine vollständige Konfiguration für den Build-Prozess sowie die Verwaltung der Abhängigkeiten.
Im Laufe der folgenden Kapitel wollen wir dir React anhand einer Beispielanwendung zeigen. Diese Anwendung wollen wir gemeinsam mit dir Schritt für Schritt entwickeln.
In diesem Kapitel stellen wir dir die Anwendung vor, damit du einen Eindruck bekommst, wie sie funktioniert und was wir dann in den folgenden Teilen implementieren werden.
Bevor wir uns die Anwendung ansehen, zeigen wir dir, wie du sie installieren und starten kannst.
Um das Beispiel zu installieren, klone dir bitte zunächst das folgende Repository:
git clone https://github.com/reactbuch/vote-example-v2.git
Das Repository enthält die folgenden Verzeichnisse:
app
: Hierunter befindet sich die vollständige, fertige Anwendung. Das Verzeichnis enthält auch eine
package.json
-Datei mit allen benötigten Abhängigkeiten sowie
npm
-Scripts zum Starten der Anwendung.
hands-on
: In diesem Verzeichnis kannst du die einzelnen Entwicklungsschritte, die wir in diesem Buch durchlaufen, nachvollziehen.
schritte
: Die darunter liegenden Verzeichnisse enthalten jeweils den aktuellen Stand der Anwendung, so wie er nach einem Kapitel vorliegt.
Weitere Informationen zum Inhalt des Repositorys und zur Verwendung der Beispiele findest du in der README-Datei im Root-Verzeichnis des Repositorys.
Die fertige Anwendung, die wir im Laufe des Buchs Schritt für Schritt entwickeln, befindet sich im Unterverzeichnis app. Das dazu passende Backend (ein auf Express basierender HTTP-Service), befindet sich im Verzeichnis voteapp-server.
Wenn du die fertige Anwendung starten und ausprobieren möchtest, öffne bitte zunächst eine Kommandozeile im Verzeichnis voteapp-server, installiere dort die nötigen npm-Pakete und starte den Server:
cd voteapp-server
npm install
npm start
Das Backend läuft auf Port 3000, dieser Port muss auf deinem Computer also frei sein.
Nun kannst du das Frontend starten. Bitte stelle zuvor sicher, dass der Port 8081, unter dem das Frontend läuft, frei ist.
Zum Starten des Frontends öffne eine neue Kommandozeile, wechsel in das Verzeichnis app und installiere dort die Pakete mit npm. Dann kannst du das Frontend starten:
cd app
npm install
npm start
In Kapitel 8 zeigen wir dir, wie du Tests für React-Anwendungen schreiben kannst. Die dabei erstellten Tests befinden sich ebenfalls unterhalb des app-Verzeichnisses, die du auch über npm ausführen kannst:
npm run test:all