2. Table of contents
Accessibility 5
Add react to a website 17
Addons animation 22
Addons create fragment 30
Addons perf 32
Addons pure render mixin 35
Addons shallow compare 36
Addons shallow renderer 37
Addons test utils 39
Addons two way binding helpers 46
Addons update 49
Addons 52
Cdn links 54
Code splitting 55
Codebase overview 61
Components and props 65
Composition vs inheritance 70
Conditional rendering 74
Context 79
Create a new react app 86
Cross origin errors 89
Design principles 91
Error boundaries 98
Error decoder 103
Faq ajax 104
Faq build 107
Faq functions 108
Faq internals 115
Faq state 116
Faq structure 119
Faq styling 121
Faq versioning 122
Forms 125
Forwarding refs 131
react
2
3. Fragments 134
Getting started 137
Handling events 141
Hello world 144
Higher order components 146
Hooks custom 155
Hooks effect 161
Hooks faq 172
Hooks intro 193
Hooks overview 198
Hooks reference 204
Hooks rules 221
Hooks state 224
How to contribute 231
Implementation notes 237
Integrating with other libraries 255
Introducing jsx 257
Jsx in depth 261
Legacy context 270
Legacy event pooling 275
Lifting state up 276
Lists and keys 284
Optimizing performance 289
Portals 299
React without es6 302
React without jsx 306
Reconciliation 307
Reference dom elements 312
Reference events 317
Reference glossary 325
Reference javascript environment requirements 330
Reference profiler 331
Reference pure render mixin 334
Reference react component 336
Reference react dom client 352
Reference react dom server 354
REACT Docs - Deutsch
3
4. Reference react dom 359
Reference react 364
Reference test renderer 374
Refs and the dom 380
Release channels 387
Render props 390
Rendering elements 397
State and lifecycle 400
Static type checking 409
Strict mode 417
Testing environments 424
Testing recipes 426
Testing 437
Thinking in react 439
Typechecking with proptypes 445
Uncontrolled components 450
Web components 452
react
4
5. Barrierefreiheit
Warum Barrierefreiheit?
Barrierefreiheit im Web (Auch bekannt unter dem Begriff a11y) beschreibt Design und Umset-
zung von Websites welche ausnahmlos von Jedem genutzt werden können. Barriefreiheit ist not-
wendig um Assistenzprogrammen das Interpretieren von Websites zu ermöglichen.
React unterstützt das Erstellen von barrierefreien Webseiten in vollem Ausmaß, unter anderem
durch die Nutzung von Standard-HTML-Technologien.
Standards und Anleitungen
WCAG
Die Web Content Accessibility Guidelines enthalten Anleitungen um barrierefreie Webseiten zu
erstellen.
Die folgenden WCAG-Checklisten geben einen kurzen Überblick:
WCAG checklist von Wuhcag
WCAG checklist von WebAIM
Checklist von dem A11Y Project
WAI-ARIA
Das Web Accessibility Initiative - Accessible Rich Internet Applications Dokument zeigt Techniken
für das Entwickeln vollkommen barrierefreier JavaScript Widgets.
Es gilt, dass alle aria-* HTML-Attribute in JSX komplett unterstützt werden. Während die meis-
ten DOM-Eigenschaften und Attribute in React in camelCase umgesetzt werden, sollten diese At-
tribute hyphen-cased (auch bekannt als kebab-case, lisp-case, usw.) sein, so wie man es auch
bei normalem HTML tun würde:
<input
type="text"
aria-label={labelText}
aria-required="true"
onChange={onchangeHandler}
value={inputValue}
name="name"
/>
Barrierefreiheit
5
6. Semantisches HTML
Semantisches HTML ist das Fundament der Barrierefreiheit einer Webanwendung. Das Nutzen der
verschiedenen HTML-Elemente, welche die Bedeutung einer Information betonen bringt dir oft-
mals Barrierefreiheit ohne extra Aufwand.
MDN HTML elements reference
Manchmal wird die Bedeutung verschiedener HTML Elemente verfälscht indem ein <div> Ele-
ment um das JSX hinzugefügt wird um den React-Code zum laufen zu bringen, besonders häufig
beim Arbeiten mit Listen ( <ol> , <ul> und <dl> ) und der HTML <table> . Hier sollten besser
React Fragments genutzt werden um mehrere Elemente in einer Gruppe zusammenzufassen.
Zum Beispiel,
Es ist auch möglich mehrere Fragmente in einem Array mit Hilfe der map -Funktion zusammenzu-
fassen, genauso wie du es bei anderen Element auch tun würdest:
Solltest du keine Props für einen Fragment-Tag brauchen kannst du die folgende short syntax
nutzen, sofern dein JS-Tooling diese unterstützt:
import React, { Fragment } from 'react';
function ListItem({ item }) {
return (
<Fragment>
<dt>{item.term}</dt>
<dd>{item.description}</dd>
</Fragment>
);
}
function Glossary(props) {
return (
<dl>
{props.items.map(item => (
<ListItem item={item} key={item.id} />
))}
</dl>
);
}
function Glossary(props) {
return (
<dl>
{props.items.map(item => (
// Fragments should also have a `key` prop when mapping collections
<Fragment key={item.id}>
<dt>{item.term}</dt>
<dd>{item.description}</dd>
</Fragment>
))}
</dl>
);
}
react
6
7. Weitere Infos findest in der Dokumentation über Fragments.
Barrierefreie Formulare
Kennzeichnung
Jedes HTML Formularelement, wie zum Beispiel <input> und <textarea> , muss barrierefrei
gekennzeichnet werden. Es müssen beschreibende Kennzeichnungen, welche für Screenreader
relevant sind, vorhanden sein.
In folgenden Quellen kannst du nachlesen wie dies am besten umzusetzen ist:
Das W3C zeigt wie Elemente zu kennzeichnen sind
WebAIM zeigt wie Elemente zu kennzeichnen sind
Die Paciello Gruppe erklärt barrierefreie Namen
Auch wenn diese HTML-Standards direkt in React genutzt werden können, solltest du darauf ach-
ten dass das for -Attribut in JSX htmlFor heißt.
Den Nutzer über Fehler informieren
Fehlersituation müssen von allen Nutzern gleich verstanden werden. Die folgenden Links zeigen
uns wie man Fehlermeldungen auch für Screenreader interpretierbar gestaltet:
Das W3C demonstriert Fehlermeldungen
WebAIM nimmt sich der Formularvalidierung an
Fokuskontrolle
Stelle sicher dass deine Webanwendung vollständig per Tastatur bedienbar ist:
WebAIM spricht über Barrierefreiheit mit Tastatur
Tastatur-Fokus und Fokussierung
Der Tastatur-Fokus zeigt auf das aktuell ausgewählte DOM-Element welches Eingaben der Tasta-
tur annimmt. Man sieht dies überall anhand der Fokussierung (Außenlinie), genau wie diese im
folgenden Bild:
function ListItem({ item }) {
return (
<>
<dt>{item.term}</dt>
<dd>{item.description}</dd>
</>
);
}
<label htmlFor="namedInput">Name:</label>
<input id="namedInput" type="text" name="name"/>
Barrierefreiheit
7
8. Verwende nur dann CSS zum Entfernen dieser Linie, zum Beispiel indem du outline: 0 setzt,
wenn du sie durch eine andere Implementierung der Fokus-Markierung ersetzt.
Mechanismen um direkt zum wichtigsten Inhalt zu springen
Stelle einen Mechanismus zur Verfügung welcher die Navigationselemente deiner Webanwendung
überspringt. Dies beschleunigt die Navigation mit der Tastatur.
Skiplinks, oder auch Skip-Navigation-Links sind versteckte Navigations-Links die nur dann sicht-
bar werden wenn Tastaturnutzer mit der Seite interagieren. Diese sind sehr einfach mit internen
Seitenankern und etwas Styling umzusetzen:
WebAIM - Skip Navigation Links
Also use landmark elements and roles, such as <main> and <aside> , to demarcate page regi-
ons as assistive technology allow the user to quickly navigate to these sections. Nutze Außerdem
semantische Elemente und Rollen, wie zum Beispiel <main> und <aside> um verschiedene Be-
reiche deiner Seite voneinander abzugrenzen, da es entprechende Assitenztechnologien so dem
User erlauben sich schnell zwischen diesen Elementen zurecht zu finden.
Mehr über den Einsatz dieser Elemente zur Verbesserung der Barrierefreiheit erfährst du hier:
Accessible Landmarks
Den Fokus programmatisch verwalten
Unsere React-Anwendungen verändern das HTML-DOM kontinuierlich zur Laufzeit, dies führt
dazu, dass der Tastatur-Fokus gelegentlich verloren geht oder auf ein unvorhersehbares Element
gesetzt wird. Um diesem Umstand zuvor zu kommen, müssen wir hier programmatisch nachhel-
fen. Zum Beispiel indem wir den Tastatur-Fokus wieder auf den Button setzen, welcher ein Modal
geöffnet hat, nachdem dieses geschlossen wurde.
MDN Web Docs takes a look at this and describes how we can build keyboard-navigable Java-
Script widgets. Die MDN Web Docs beschreiben wie wir Tastaturgesteurte JavaScript Widgets rea-
lisieren können.
Um mit React einen Fokus zu setzen, können wir Refs auf DOM-Elementen nutzen.
Hierzu erstellen wir zuerst eine Elementreferenz im JSX einer Component-Klasse:
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
// Create a ref to store the textInput DOM element
this.textInput = React.createRef();
}
render() {
react
8
9. Danach können wir den Fokus beliebig verändern, falls nötig:
Gelegentlich ist es nötig, dass eine Eltern-Komponente den Fokus auf ein Element einer Kind-
Komponente setzen muss. Dies lässt sich mit dem Bereitstellen von DOM-Referenzen einer El-
tern-Komponente mit einer speziellen Eigenschaft, welche die Referenz der Eltern-Komponente
zur Kind-Komponente weitergibt, umsetzen.
Falls du eine HOC nutzt empfiehlt es sich die Referenz zur umschlossenen Komponente weiterzu-
geben indem du die forwardRef React-Funktion nutzt. Sollte eine Drittanbieter HOC diese Tech-
nik nicht implementiert haben kannst du das oben verwendete Pattern als einen Fallback nutzen.
Ein gutes Fokus-Beispielt ist das react-aria-modal. Dies ist ein relativ rares Beispiel eines voll-
ständig barrierefreiem Modal-Fenster. Hier wird der initiale Fokus auf den Abbrechen Button ge-
setzt (Um den User davon abzuhalten versehentlich die Success-Action zu aktivieren) und der Fo-
kus kann nicht aus dem Modal-Fenster springen. Nachdem das Modal geschlossen wird wird der
Fokus wieder zurück auf das Element gesetzt welches das Modal-Fenster getriggered hat.
// Use the `ref` callback to store a reference to the text input DOM
// element in an instance field (for example, this.textInput).
return (
<input
type="text"
ref={this.textInput}
/>
);
}
}
focus() {
// Explicitly focus the text input using the raw DOM API
// Note: we're accessing "current" to get the DOM node
this.textInput.current.focus();
}
function CustomTextInput(props) {
return (
<div>
<input ref={props.inputRef} />
</div>
);
}
class Parent extends React.Component {
constructor(props) {
super(props);
this.inputElement = React.createRef();
}
render() {
return (
<CustomTextInput inputRef={this.inputElement} />
);
}
}
// Now you can set focus when required.
this.inputElement.current.focus();
Barrierefreiheit
9
10. Hinweis:
Es handelt sich hier um ein wichtiges Feature, welches jedoch in einem vernünftigen Rah-
men genutzt werden sollte. Nutze dieses Feature, um den Tastatur-Fokus anzupassen, falls
der Flow der App gestört sein sollte und versuche nicht, die Tastaturnutzung des Users zu
antizipieren.
Maus- und Pointerevents
Stelle sicher, dass alle Funktionalitäten, welche durch die Maus oder den Zeiger hervorgerufen
werden, auch via Tastatur gesteuert werden können. Sich komplett von einem Zeigergerät ab-
hängig zu machen, führt dazu, dass deine App für viele Tastaturnutzer unbrauchbar wird.
Um dies zu verdeutlichen, schauen wir uns ein Anwendungsbeispiel an, bei dem die Barrierefrei-
heit durch Click-Events gestört ist. Hier siehst du das "outside-click"-Pattern, in welchem der User
eine geöffnete Popup-Nachricht schließen kann, indem er außerhalb des Elements klickt.
Typischerweise wird Dies durch ein Klick-Event auf dem window -Objekt implementiert welches
die Popover-Nachricht schließt:
class OuterClickExample extends React.Component {
constructor(props) {
super(props);
this.state = { isOpen: false };
this.toggleContainer = React.createRef();
this.onClickHandler = this.onClickHandler.bind(this);
this.onClickOutsideHandler = this.onClickOutsideHandler.bind(this);
}
componentDidMount() {
window.addEventListener('click', this.onClickOutsideHandler);
}
componentWillUnmount() {
window.removeEventListener('click', this.onClickOutsideHandler);
}
onClickHandler() {
react
10
11. Dies würde natürlich mit Zeigergeräten, wie zB. der Maus, super funktionieren, mit der Tastatur
alleine führt dies jedoch zu mangelhafter Funktionalität wenn du das nächste Element per Tab er-
reichst. In diesem Fall das click -Event nie auf dem window -Objekt aufgerufen. Dies kann zu
obskuren Fehlern führen, welche es manchen Usern unmöglich macht deine App zu nutzen.
Die gleiche Funktionalität kann durch geeignete Eventhandler, wie zum Beispiel onBLur und
onFocus , erreicht werden:
this.setState(currentState => ({
isOpen: !currentState.isOpen
}));
}
onClickOutsideHandler(event) {
if (this.state.isOpen && !this.toggleContainer.current.contains(event.target)) {
this.setState({ isOpen: false });
}
}
render() {
return (
<div ref={this.toggleContainer}>
<button onClick={this.onClickHandler}>Select an option</button>
{this.state.isOpen && (
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
)}
</div>
);
}
}
class BlurExample extends React.Component {
constructor(props) {
super(props);
this.state = { isOpen: false };
this.timeOutId = null;
this.onClickHandler = this.onClickHandler.bind(this);
this.onBlurHandler = this.onBlurHandler.bind(this);
this.onFocusHandler = this.onFocusHandler.bind(this);
Barrierefreiheit
11
12. Der obige Code gewährleistet die Funktionalität sowohl für Zeigergeräte als auch für Tastaturen.
Beachte auch die aria-* Attribute zur Unterstützung von Screenreadern. Der Einfachheit halber
wurden hier keine Pfeiltasten-Events implementiert um mit dem Popover zu interagieren.
}
onClickHandler() {
this.setState(currentState => ({
isOpen: !currentState.isOpen
}));
}
// We close the popover on the next tick by using setTimeout.
// This is necessary because we need to first check if
// another child of the element has received focus as
// the blur event fires prior to the new focus event.
onBlurHandler() {
this.timeOutId = setTimeout(() => {
this.setState({
isOpen: false
});
});
}
// If a child receives focus, do not close the popover.
onFocusHandler() {
clearTimeout(this.timeOutId);
}
render() {
// React assists us by bubbling the blur and
// focus events to the parent.
return (
<div onBlur={this.onBlurHandler}
onFocus={this.onFocusHandler}>
<button onClick={this.onClickHandler}
aria-haspopup="true"
aria-expanded={this.state.isOpen}>
Select an option
</button>
{this.state.isOpen && (
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
)}
</div>
);
}
}
react
12
13. Dies hier ist nur ein Beispiel für viele Fälle bei denen die Funktionalität nicht gewährleistet ist
wenn du dich nur auf Zeiger-Events verlässt. Ein beständiges Testen mit der Tastutur zeigt dir
auch die Schwachstellen, welche mit angemessenen Eventhandlern beseitigt werden können.
Kompliziertere Widgets
Kompliziertere Handlungen sollten nicht mit weniger Barrierefreiheit einhergehen. Während Bar-
rierefreiheit am einfachen damit umgesetzt werden kann sich so gut wie möglich an den HTML-
Standard zu halten, können auch die kompliziertesten Widgets barrierefrei implementiert werden.
Here we require knowledge of ARIA Roles as well as ARIA States and Properties. Wir setzen hier
Grundkentinsse in den ARIA Rollen sowie den ARIA Zuständen und Eigenschaften hervor.
Jede Art von Widget hat ein spezielles Designpattern und sollte für User und deren Useragents
wie folgt funktionieren:
WAI-ARIA Konventionen - Designppatterns und Widgets
Heydon Pickering - ARIA Beispiele
Inclusive Components
Andere wichtige Punkte
Einstellung der Sprache
Gib immer die in den Texten deiner Seite verwendete Sprache an, da Screen-Reader-Software
diese Angabe nutzt um die richtigen Spracheinstellungen auszuwählen.
WebAIM - Document Language
Der Titel des Dokuments
Verwende den Dokumenten <title> um den aktuellen Inhalt der Seite korrekt zu beschreiben,
da dies sicherstellt, dass der Benutzer über den aktuellen Seitenkontext informiert ist.
WCAG - Den Bedarf eines Dokumenten-Titels verstehen
In React können wir Diesen mit dem React Document Title Component realisieren.
Barrierefreiheit
13
14. Farbkontraste
Stelle sicher, dass die Texte deiner Webseite ausreichende Farbkontraste aufweisen, um auch von
Nutzern mit Sehschwäche problemlos lesbar zu sein:
WCAG - Den Bedarf für Farbkontrast verstehen
Alles über den Farbkontrast und warum man ihn überdenken sollte
A11yProject - Was ist Farbkontrast
Es kann sehr anstrengend sein die richtigen Farbkombinationen für alle Anwendungsfälle deiner
Webseite manuell zu erstellen, anstatt dessen kannst du eine vollständig barrierefreie Farbpalette
mit Colorable berechnen.
Sowohl die unten erwähnten aXe als auch die WAVE-Werkzeuge beinhalten Farbkontrast-Tests
welche dich über fehlerhafte Kontraste informieren.
Wenn du deine Kontraste noch genauer testen willst kannst du die folgenden Werkzeuge
verwenden:
WebAIM - Farbkontrast Checker
Die Paciello Gruppe - Farbkontrast Analyzer
Entwicklungs- und Testingtools
Es gibt eine Reihe von Werkzeugen um dich bei der Erstellung barrierefreier Webanwendungen zu
unterstützen.
Die Tastatur
Die mit Abstand einfachste und auch eine der wichtigsten Prüfungen ist es, zu testen, ob deine
gesamte Webseite allein mit der Tastatur erreichbar und nutzbar ist. Teste dies wie folgt:
1. Deaktiviere deine Maus.
2. Nutze Tab und Shift+Tab um zu navigieren.
3. Nutze Enter um Elemente zu aktivieren.
4. Falls nötig, nutze die Pfeiltasten zur Interaktion mit manchen Elementen, wie z.B. Menüs und
Dropdowns.
Hilfsmittel für Entwickler
Einige Punkte der Barrierefreiheit können direkt in unserem JSX-Code getestet werden. Oftmals
gibt es bereits Intellisense-Tests für ARIA-Roles, States und Properties in JSX-fähigen IDE's. Au-
ßerdem steht uns das folgende Werkzeug zur Verfügung:
eslint-plugin-jsx-a11y
Das eslint-plugin-jsx-a11y ESLint-Plugin stellt AST-Linting-Feedback bezogen auf Probleme mit
der Barrierefreiheit in deinem JSX zur Verfügung. Viele IDE's machen es dir möglich diese Funk-
tionalität direkt in die Code-Analyse oder die Coding-Oberfläche zu integrieren.
react
14
15. Create React App verfügt über ein Plugin welches einen Teil dieser Regeln aktiviert hat. Solltest
du noch mehr Regeln zur Barrierefreiheit nutzen wollen, kannst im Stammverzeichnis deines Pro-
jekts eine .eslintrc -Datei mit folgendem Inhalt anlegen:
Barrierefreiheit im Browser testen
Es gibt eine Reihe von Werkzeugen, die Barrierefreiheitsprüfungen auf deinen Webseiten im
Browser durchführen können. Bitte nutze Diese nur in Verbindung mit den bereits genannten
Werkzeugen, da diese Tests nur die technische Barrierefreiheit in deinem HTML kontrollieren
können.
aXe, aXe-core und react-axe
Deque Systems bietet aXe-core für automatisierte End-to-End-Tests deiner Anwendung an. Die-
ses Modul enthält auch Einbindungen für Selenium.
The Accessibility Engine, oder aXe, ist eine Browser-Erweiterung basierend auf aXe-core , die ei-
nen Inspektor für Barrierefreiheit bereitstellt.
Außerdem kannst du das @axe-core/react Modul nutzen, um die Ergebnisse dieser Barrierefrei-
heitskontrollen während der Entwicklung direkt in der Konsole auszugeben.
WebAIM WAVE
Das Web Accessibility Evaluation Tool ist eine weitere Browser-Erweiterung.
Barrierefreiheitsprüfer und der Barrierefreiheitsbaum
Der Barrierefreiheitsbaum ist eine Teilmenge des DOM-Baums, welche barrierefreie Objekte für
jedes DOM-Element, das für unterstützende Technologie wie z. B. Screen-Readern sichtbar sein
sollte, enthält.
In einigen Browsern ist es einfach möglich die Informationen zur Barrierefreiheit für jedes Ele-
ment des Barrierefreiheitsbaums zu überprüfen:
Den Barrierefreiheitsprüfer in Firefox nutzen
Den Barrierefreiheitsprüfer in Chrome nutzen
Den Barrierefreiheitsprüfer in OS X Safari nutzen
Screen-Reader
Das Testen mit einem Screen-Reader sollte bei deinen Tests zur Barrierefreiheit nicht fehlen.
Beachte dass es auf die Browser / Screen-Reader Kombination ankommt. Es wird empfohlen,
dass du deine Anwendung in dem Browser testest, der am besten zu deinem gewählten Screen-
Reader passt.
{
"extends": ["react-app", "plugin:jsx-a11y/recommended"],
"plugins": ["jsx-a11y"]
}
Barrierefreiheit
15
16. Häufig genutzte Screen-Reader
NVDA im Firefox
NonVisual Desktop Access, auch NVDA, ist ein häufig genutzter Screen-Reader für Windows.
Nutze die folgenden Hinweise, um zu erfahren wie NVDA am besten zu nutzen ist:
WebAIM - NVDA zur Auswertung der Web-Barrierefreiheit
Deque - NVDA Tastenkombinationen
VoiceOver im Safari
VoiceOver ist ein in Apple-Geräte integrierter Screen-Reader.
Nutze die folgenden Hinweise, um zu erfahren wie man VoiceOver aktiviert:
WebAIM - VoiceOver zur Auswertung der Web-Barrierefreiheit
Deque - VoiceOver für OS X Tastenkombinationen
Deque - VoiceOver für iOS Kombinationen
JAWS im Internet Explorer
Job Access With Speech, auch JAWS, ist ein häufig genutzter Screen-Reader für Windows.
Nutze die folgenden Hinweise, um zu erfahren wie JAWS am besten zu nutzen ist:
WebAIM - JAWS zur Auswertung der Web-Barrierefreiheit
Deque - JAWS Tastenkombinationen
Weitere Screen-Reader
ChromeVox im Google Chrome
ChromeVox ist ein in Chromebooks integrierter Screen-Reader und ist außerdem als eine Erweite-
rung für Chrome verfügbar.
Nutze die folgenden Hinweise, um zu erfahren wie ChromeVox am besten zu nutzen ist:
Google Chromebook Hilfe - Nutzung des integrierten Screen-Readers
ChromeVox Referenz der klassischen Tastenkombinationen
react
16
17. React einer Webseite hinzufügen
Verwende so wenig oder so viel React wie du möchtest.
React wurde von Beginn an für eine schrittweise Benutzung konzipiert und du kannst so wenig
oder so viel React benutzen, wie du möchtest. Vielleicht möchtest du zu einer existierenden Seite
nur an wenigen Stellen ein paar kleine "Spritzer von Interaktivität" hinzufügen. React Komponen-
ten sind perfekt dafür geeignet.
Die Mehrheit der Webseiten sind und brauchen keine SPAs zu sein. Probiere React in einem klei-
nen Teil deiner Webseite mit ein paar Zeilen Code und ohne Build-Werkzeuge aus. Dann
kannst du die Verwendung entweder schrittweise erweitern oder auf ein paar dynamische Wid-
gets beschränken.
Füge React in einer Minute hinzu
Optional: Benutze React mit JSX (Kein Bundler benötigt!)
Füge React in einer Minute hinzu
Wir wollen in diesem Abschnitt zeigen, wie man einer existierenden HTML Seite eine React Kom-
ponente hinzufügen kann. Um zu üben kannst du deine eigene Webseite benutzen oder eine leere
HTML Seite erstellen.
Es sind keine komplizierten Werkzeuge oder Installationen nötig -- Um diesem Abschnitt zu
folgen, brauchst du nur eine Internetverbindung und eine Minute deiner Zeit.
Optional: Komplettes Beispiel herunterladen (2KB gezippt)
Schritt 1: Einen DOM Container dem HTML hinzufügen
Öffne als erstes die HTML Seite, die du editieren möchtest. Füge ein leeres <div> Tag hinzu, um
die Stelle zu markieren, an der du mit React etwas anzeigen möchtest. Zum Beispiel:
Wir haben diesem div ein eindeutiges id HTML Attribut gegeben. Das erlaubt es uns es später
mit JavaScript wiederzufinden und darin eine React Komponente anzuzeigen.
Tipp
<!-- ... existierendes HTML ... -->
<div id="like_button_container"></div>
<!-- ... existierendes HTML ... -->
React einer Webseite hinzufügen
17
18. Du kannst einen "Container" <div> wie das oben überall im <body> Tag setzen. Du
kannst so viele unabhängige DOM Container in einer Seite haben wie du brauchst. Norma-
lerweise sind sie leer -- Falls die DOM Container Inhalt besitzen, wird React diesen
überschreiben.
Schritt 2: Füge die Script Tags hinzu
Als nächstes fügen wir direkt vor dem schließenden </body> Tag drei <script> Tags der HTML
Seite hinzu:
Die ersten zwei Tags laden React. Der dritte läd deinen Komponenten Code.
Schritt 3: Erstelle eine React Komponente
Erstelle eine Datei mit dem Namen like_button.js und speichere sie neben deiner HTML Seite.
Öffne den Starter Code und füge Sie in die Datei ein, die du erstellt hast.
Tipp
Dieser Code definiert eine React Komponente mit dem Namen LikeButton . Mach dir keine
Sorgen, falls du das noch nicht verstehst -- Wir werden die Bausteine von React später in
unserem hands-on Tutorial und dem Leitfaden der Hauptkonzepte behandeln. Jetzt wollen
wir sie erstmal im Browser angezeigt bekommen!
Nach dem Starter Code, füge zwei Zeilen am Ende von like_button.js an:
Diese drei Codezeilen finden den <div> Container aus dem ersten Schritt und zeigen dann unse-
re React Komponente mit dem "Like" Button darin an.
<!-- ... anderes HTML ... -->
<!-- React laden. -->
<!-- Hinweis: Wenn du die Seite bereitstellen willst, ersetze "development.js" mit "product
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></scr
<!-- Unsere React Komponente laden. -->
<script src="like_button.js"></script>
</body>
// ... Der Start Code, den du gerade eingefügt hast ...
const domContainer = document.querySelector('#like_button_container');
const root = ReactDOM.createRoot(domContainer);
root.render(e(LikeButton));
react
18
19. Das ist alles!
Es gibt keinen vierten Schritt. Du hast gerade deine erste React Komponente zu deiner
Webseite hinzugefügt.
Sieh dir die nächsten Abschnitte an, um mehr Tipps zu erhalten, wie du React integrieren kannst.
Öffne den ganzen Beispiel Source Code
Das komplette Beispiel herunterladen (2KB gezippt)
Tipp: Verwende Komponeten wieder
Häufig wirst du React Komponenten an verschiedenen Stellen einer HTML Seite anzeigen wollen.
Hier ist ein Beispiel, welches den "Like" Button dreimal anzeigt und einige Daten hinzufügt.
Öffne den ganzen Beispiel Source Code
Das komplette Beispiel herunterladen (2KB gezippt)
Hinweis
Diese Herangehensweise ist besonders sinnvoll, wenn mit React gebaute Teile der Seite
voneinander isoliert sind. In React Code selbst ist es einfacher stattdessen Komponenten
Komposition zu verwenden.
Tipp: Minifiziere JavaScript für die Produktionsumgebung
Bevor du deine Webseite für die Produktionsumgebung deployst, denke daran, dass unminifizier-
tes JavaScript die Seite für deine User signifankt verlangsamen kann.
Falls du bereits die Anwendungsscripts minifiziert hast, ist deine Seite fertig für die Produkti-
onsumgebung, sobald du sichergestellt hast, dass das bereitgestellte HTML die Versionen von
React lädt, die auf production.min.js enden:
Falls du deine Skripte nicht minifizierst, wird hier wird ein möglicher Weg zur Minifizierung
gezeigt.
Optional: Benutze React mit JSX
In den Beispielen haben wir nur Funktionalitäten verwendet, die von Browsern nativ unterstützt
werden. Deswegen haben wir einen Methodenaufruf in JavaScript benutzt, um React zu sagen,
was angezeigt werden soll:
<script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></sc
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossori
React einer Webseite hinzufügen
19
20. React bietet allerdings auch die Option an, stattdessen JSX zu benutzen.
Diese zwei Codebeispiele sind äquivalent. Obwohl JSX komplett optional ist, finden es viele
Leute beim Schreiben von UI Code hilfreich -- sowohl mit React als auch mit anderen
Bibliotheken.
Du kannst JSX mit diesem Online Konverter ausprobieren.
Schnell JSX ausprobieren
Du kannst JSX in deinem Projekt am schnellsten ausprobieren, indem du diesen <script> Tag
deiner Seite hinzufügst:
Jetzt kannst JSX in jedem <script> Tag verwenden, indem du diesem ein type="text/babel"
Attribut hinzufügst. Hier kannst du eine Besipiel HTML Datei mit JSX herunterladen und mit ihr
experimentieren.
Um zu lernen und einfache Demos zu bauen ist dieser Ansatz ausreichend. Allerdings macht er
deine Webseite langsam und ist nicht für die Produktionsumgebung geeignet. Wenn du be-
reit bist weiter zu machen, entferne den neuen <script> Tag und das type="text/babel" ,
das du eben hinzugefügt hast. Im nächsten Abschnitt wirst du stattdessen einen JSX Präprozes-
sor aufsetzen, der alle deine <script> Tags automatisch konvertiert.
Füge JSX einem Projekt hinzu
Einem Projekt JSX hinzuzufügen benötigt keine komplizierten Werkzeuge wie einen Bundler oder
einen Entwicklungsserver. JSX einbinden ist ähnlich wie einen CSS Präprozessor einzubin-
den. Als einzige Voraussetzung musst du Node.js auf deinem Computer installiert haben.
Navigiere im Terminal zu deinem Projektordner und führe diese zwei Befehle aus:
1. Schritt 1: Führe npm init -y aus (falls es fehlgeschlägt, gibt es hier Hilfe)
2. Schritt 2: Führe npm install babel-cli@6 babel-preset-react-app@3 aus
const e = React.createElement;
// Zeige einen "Like" <button> an
return e(
'button',
{ onClick: () => this.setState({ liked: true }) },
'Like'
);
// Zeige einen "Like" <button> an
return (
<button onClick={() => this.setState({ liked: true })}>
Like
</button>
);
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
react
20
21. Tipp
Wir benutzen hier npm nur, um den JSX Präprozessor zu installieren; Du wirst es für
nichts anderes brauchen. Sowohl React als auch der Anwendungscode können ohne Ände-
rung weiter als <script> Tags eingebunden werden.
Herzlichen Glückwunsch! Du hast gerade ein JSX Setup eingerichtet, das für die Produktions-
umgebung bereit ist.
Starte den JSX Präprozessor
Erzeuge einen Ordner mit dem Namen src und führe folgenden Befehl aus:
Hinweis
npx ist kein Schreibfehler -- es ist ein Werkzeug um Pakete direkt auszuführen (package
runner tool), welches seit npm 5.2 mitgeliefert wird
Falls du eine Fehlermeldung mit dem Text "You have mistakenly installed the babel packa-
ge" siehst, hast du vielleicht den vorherigen Schritt übersprungen. Führe diesen im gleichen
Ordner aus und probier es nochmal.
Du brauchst nicht darauf zu warten, dass der Befehl fertig ausgeführt wird -- er startet einen au-
tomatisierten Watcher für JSX.
Wenn du jetzt eine Datei unter src/like_button.js mit diesem JSX Starter Code erstellst,
wird der Watcher eine präprozessierte like_button.js mit einfachem JavaScript Code erstellen,
der im Browser ausgeführt werden kann. Wenn Sie die Quelldatei mit JSX bearbeiten, wird das
Bauen der Datei automatisch erneut ausgeführt.
Zusätzlich kannst du durch diesen Ansatz moderne JavaScript Syntax Funktionalitäten wie Klas-
sen verwenden, ohne dass dein Code in alten Browsern nicht funktionieren würde.
Falls du merkst, dass du im Umgang mit Build-Werkzeugen sicher wirst und du von ihnen mehr
machen lassen willst, beschreibt der nächste Abschnitt einige der beliebtesten und zugänglichs-
ten Ansammlungen von diesen. Falls aber nicht -- Script Tags sind genauso ok!
npx babel --watch src --out-dir . --presets react-app/prod
React einer Webseite hinzufügen
21
22. Animation Add-Ons
Note:
ReactTransitionGroup and ReactCSSTransitionGroup have been moved to the react-
transition-group package that is maintained by the community. Its 1.x branch is com-
pletely API-compatible with the existing addons. Please file bugs and feature requests in
the new repository.
The ReactTransitionGroup add-on component is a low-level API for animation, and React‐
CSSTransitionGroup is an add-on component for easily implementing basic CSS animations and
transitions.
High-level API: ReactCSSTransitionGroup
ReactCSSTransitionGroup is a high-level API based on ReactTransitionGroup and is an easy
way to perform CSS transitions and animations when a React component enters or leaves the
DOM. It's inspired by the excellent ng-animate library.
Importing
import ReactCSSTransitionGroup from 'react-transition-group'; // ES6
var ReactCSSTransitionGroup = require('react-transition-group'); // ES5 with npm
class TodoList extends React.Component {
constructor(props) {
super(props);
this.state = {items: ['hello', 'world', 'click', 'me']};
this.handleAdd = this.handleAdd.bind(this);
}
handleAdd() {
const newItems = this.state.items.concat([
prompt('Enter some text')
]);
this.setState({items: newItems});
}
handleRemove(i) {
let newItems = this.state.items.slice();
newItems.splice(i, 1);
this.setState({items: newItems});
}
render() {
const items = this.state.items.map((item, i) => (
<div key={i} onClick={() => this.handleRemove(i)}>
{item}
</div>
));
react
22
23. Note:
You must provide the key attribute for all children of ReactCSSTransitionGroup , even
when only rendering a single item. This is how React will determine which children have en-
tered, left, or stayed.
In this component, when a new item is added to ReactCSSTransitionGroup it will get the ex‐
ample-enter CSS class and the example-enter-active CSS class added in the next tick. This
is a convention based on the transitionName prop.
You can use these classes to trigger a CSS animation or transition. For example, try adding this
CSS and adding a new list item:
You'll notice that animation durations need to be specified in both the CSS and the render me-
thod; this tells React when to remove the animation classes from the element and -- if it's leaving
-- when to remove the element from the DOM.
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
<ReactCSSTransitionGroup
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}>
{items}
</ReactCSSTransitionGroup>
</div>
);
}
}
.example-enter {
opacity: 0.01;
}
.example-enter.example-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}
.example-leave {
opacity: 1;
}
.example-leave.example-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
}
Animation Add-Ons
23
24. Animate Initial Mounting
ReactCSSTransitionGroup provides the optional prop transitionAppear , to add an extra
transition phase at the initial mount of the component. There is generally no transition phase at
the initial mount as the default value of transitionAppear is false . The following is an ex-
ample which passes the prop transitionAppear with the value true .
During the initial mount ReactCSSTransitionGroup will get the example-appear CSS class and
the example-appear-active CSS class added in the next tick.
At the initial mount, all children of the ReactCSSTransitionGroup will appear but not enter .
However, all children later added to an existing ReactCSSTransitionGroup will enter but not
appear .
Note:
The prop transitionAppear was added to ReactCSSTransitionGroup in version 0.13 .
To maintain backwards compatibility, the default value is set to false .
However, the default values of transitionEnter and transitionLeave are true so you
must specify transitionEnterTimeout and transitionLeaveTimeout by default. If you
don't need either enter or leave animations, pass transitionEnter={false} or transi‐
tionLeave={false} .
render() {
return (
<ReactCSSTransitionGroup
transitionName="example"
transitionAppear={true}
transitionAppearTimeout={500}
transitionEnter={false}
transitionLeave={false}>
<h1>Fading at Initial Mount</h1>
</ReactCSSTransitionGroup>
);
}
.example-appear {
opacity: 0.01;
}
.example-appear.example-appear-active {
opacity: 1;
transition: opacity .5s ease-in;
}
react
24
25. Custom Classes
It is also possible to use custom class names for each of the steps in your transitions. Instead of
passing a string into transitionName you can pass an object containing either the enter and
leave class names, or an object containing the enter , enter-active , leave-active , and
leave class names. If only the enter and leave classes are provided, the enter-active and leave-
active classes will be determined by appending '-active' to the end of the class name. Here are
two examples using custom classes:
Animation Group Must Be Mounted To Work
In order for it to apply transitions to its children, the ReactCSSTransitionGroup must already
be mounted in the DOM or the prop transitionAppear must be set to true .
The example below would not work, because the ReactCSSTransitionGroup is being mounted
along with the new item, instead of the new item being mounted within it. Compare this to the
Getting Started section above to see the difference.
// ...
<ReactCSSTransitionGroup
transitionName={ {
enter: 'enter',
enterActive: 'enterActive',
leave: 'leave',
leaveActive: 'leaveActive',
appear: 'appear',
appearActive: 'appearActive'
} }>
{item}
</ReactCSSTransitionGroup>
<ReactCSSTransitionGroup
transitionName={ {
enter: 'enter',
leave: 'leave',
appear: 'appear'
} }>
{item2}
</ReactCSSTransitionGroup>
// ...
render() {
const items = this.state.items.map((item, i) => (
<div key={item} onClick={() => this.handleRemove(i)}>
<ReactCSSTransitionGroup transitionName="example">
{item}
</ReactCSSTransitionGroup>
</div>
));
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
{items}
Animation Add-Ons
25
26. Animating One or Zero Items
In the example above, we rendered a list of items into ReactCSSTransitionGroup . However,
the children of ReactCSSTransitionGroup can also be one or zero items. This makes it possible
to animate a single element entering or leaving. Similarly, you can animate a new element repla-
cing the current element. For example, we can implement a simple image carousel like this:
Disabling Animations
You can disable animating enter or leave animations if you want. For example, sometimes
you may want an enter animation and no leave animation, but ReactCSSTransitionGroup
waits for an animation to complete before removing your DOM node. You can add transition‐
Enter={false} or transitionLeave={false} props to ReactCSSTransitionGroup to disable
these animations.
Note:
When using ReactCSSTransitionGroup , there's no way for your components to be noti-
fied when a transition has ended or to perform any more complex logic around animation.
If you want more fine-grained control, you can use the lower-level ReactTransitionGroup
API which provides the hooks you need to do custom transitions.
Low-level API: ReactTransitionGroup
Importing
</div>
);
}
import ReactCSSTransitionGroup from 'react-transition-group';
function ImageCarousel(props) {
return (
<div>
<ReactCSSTransitionGroup
transitionName="carousel"
transitionEnterTimeout={300}
transitionLeaveTimeout={300}>
<img src={props.imageSrc} key={props.imageSrc} />
</ReactCSSTransitionGroup>
</div>
);
}
import ReactTransitionGroup from 'react-addons-transition-group' // ES6
var ReactTransitionGroup = require('react-addons-transition-group') // ES5 with npm
react
26
27. ReactTransitionGroup is the basis for animations. When children are declaratively added or re-
moved from it (as in the example above), special lifecycle methods are called on them.
componentWillAppear()
componentDidAppear()
componentWillEnter()
componentDidEnter()
componentWillLeave()
componentDidLeave()
Rendering a Different Component
ReactTransitionGroup renders as a span by default. You can change this behavior by provi-
ding a component prop. For example, here's how you would render a <ul> :
Any additional, user-defined, properties will become properties of the rendered component. For
example, here's how you would render a <ul> with CSS class:
Every DOM component that React can render is available for use. However, component does not
need to be a DOM component. It can be any React component you want; even ones you've writ-
ten yourself! Just write component={List} and your component will receive this.prop‐
s.children .
Rendering a Single Child
People often use ReactTransitionGroup to animate mounting and unmounting of a single child
such as a collapsible panel. Normally ReactTransitionGroup wraps all its children in a span
(or a custom component as described above). This is because any React component has to re-
turn a single root element, and ReactTransitionGroup is no exception to this rule.
However if you only need to render a single child inside ReactTransitionGroup , you can com-
pletely avoid wrapping it in a <span> or any other DOM component. To do this, create a custom
component that renders the first child passed to it directly:
Now you can specify FirstChild as the component prop in <ReactTransitionGroup> props
and avoid any wrappers in the result DOM:
<ReactTransitionGroup component="ul">
{/* ... */}
</ReactTransitionGroup>
<ReactTransitionGroup component="ul" className="animated-list">
{/* ... */}
</ReactTransitionGroup>
function FirstChild(props) {
const childrenArray = React.Children.toArray(props.children);
return childrenArray[0] || null;
}
Animation Add-Ons
27
28. This only works when you are animating a single child in and out, such as a collapsible panel.
This approach wouldn't work when animating multiple children or replacing the single child with
another child, such as an image carousel. For an image carousel, while the current image is ani-
mating out, another image will animate in, so <ReactTransitionGroup> needs to give them a
common DOM parent. You can't avoid the wrapper for multiple children, but you can customize
the wrapper with the component prop as described above.
Reference
componentWillAppear() {#componentwillappear}
This is called at the same time as componentDidMount() for components that are initially moun-
ted in a TransitionGroup . It will block other animations from occurring until callback is cal-
led. It is only called on the initial render of a TransitionGroup .
componentDidAppear() {#componentdidappear}
This is called after the callback function that was passed to componentWillAppear is called.
componentWillEnter() {#componentwillenter}
This is called at the same time as componentDidMount() for components added to an existing
TransitionGroup . It will block other animations from occurring until callback is called. It will
not be called on the initial render of a TransitionGroup .
componentDidEnter() {#componentdidenter}
This is called after the callback function that was passed to componentWillEnter() is called.
componentWillLeave() {#componentwillleave}
<ReactTransitionGroup component={FirstChild}>
{someCondition ? <MyComponent /> : null}
</ReactTransitionGroup>
componentWillAppear(callback)
componentDidAppear()
componentWillEnter(callback)
componentDidEnter()
componentWillLeave(callback)
react
28
29. This is called when the child has been removed from the ReactTransitionGroup . Though the
child has been removed, ReactTransitionGroup will keep it in the DOM until callback is
called.
componentDidLeave() {#componentdidleave}
This is called when the willLeave callback is called (at the same time as componentWillUn‐
mount() ).
componentDidLeave()
Animation Add-Ons
29
30. Keyed Fragments
Note:
React.addons entry point is deprecated as of React v15.5. We now have first class sup-
port for fragments which you can read about here.
Importing
Overview
In most cases, you can use the key prop to specify keys on the elements you're returning from
render . However, this breaks down in one situation: if you have two sets of children that you
need to reorder, there's no way to put a key on each set without adding a wrapper element.
That is, if you have a component such as:
The children will unmount and remount as you change the swapped prop because there aren't
any keys marked on the two sets of children.
To solve this problem, you can use the createFragment add-on to give keys to the sets of
children.
Array<ReactNode> createFragment(object children) {#arrayreactnode-createfrag-
mentobject-children}
Instead of creating arrays, we write:
import createFragment from 'react-addons-create-fragment'; // ES6
var createFragment = require('react-addons-create-fragment'); // ES5 with npm
function Swapper(props) {
let children;
if (props.swapped) {
children = [props.rightChildren, props.leftChildren];
} else {
children = [props.leftChildren, props.rightChildren];
}
return <div>{children}</div>;
}
import createFragment from 'react-addons-create-fragment';
function Swapper(props) {
let children;
if (props.swapped) {
children = createFragment({
right: props.rightChildren,
react
30
31. The keys of the passed object (that is, left and right ) are used as keys for the entire set of
children, and the order of the object's keys is used to determine the order of the rendered child-
ren. With this change, the two sets of children will be properly reordered in the DOM without
unmounting.
The return value of createFragment should be treated as an opaque object; you can use the
React.Children helpers to loop through a fragment but should not access it directly. Note also
that we're relying on the JavaScript engine preserving object enumeration order here, which is
not guaranteed by the spec but is implemented by all major browsers and VMs for objects with
non-numeric keys.
left: props.leftChildren
});
} else {
children = createFragment({
left: props.leftChildren,
right: props.rightChildren
});
}
return <div>{children}</div>;
}
Keyed Fragments
31
32. Performance Tools
Note:
As of React 16, react-addons-perf is not supported. Please use your browser's profiling
tools to get insight into which components re-render.
Importing
Overview
React is usually quite fast out of the box. However, in situations where you need to squeeze every
ounce of performance out of your app, it provides a shouldComponentUpdate() method where
you can add optimization hints to React's diff algorithm.
In addition to giving you an overview of your app's overall performance, Perf is a profiling tool
that tells you exactly where you need to put these methods.
See these articles for an introduction to React performance tooling:
"How to Benchmark React Components"
"Performance Engineering with React"
"A Deep Dive into React Perf Debugging"
Development vs. Production Builds
If you're benchmarking or seeing performance problems in your React apps, make sure you're
testing with the minified production build. The development build includes extra warnings that
are helpful when building your apps, but it is slower due to the extra bookkeeping it does.
However, the perf tools described on this page only work when using the development build of
React. Therefore, the profiler only serves to indicate the relatively expensive parts of your app.
Using Perf
The Perf object can be used with React in development mode only. You should not include this
bundle when building your app for production.
Getting Measurements
start()
stop()
import Perf from 'react-addons-perf'; // ES6
var Perf = require('react-addons-perf'); // ES5 with npm
react
32
33. getLastMeasurements()
Printing Results
The following methods use the measurements returned by Perf.getLastMeasurements() to
pretty-print the result.
printInclusive()
printExclusive()
printWasted()
printOperations()
printDOM()
Reference
start() {#start}
stop() {#stop}
Start/stop the measurement. The React operations in-between are recorded for analyses below.
Operations that took an insignificant amount of time are ignored.
After stopping, you will need Perf.getLastMeasurements() to get the measurements.
getLastMeasurements() {#getlastmeasurements}
Get the opaque data structure describing measurements from the last start-stop session. You can
save it and pass it to the other print methods in Perf to analyze past measurements.
Note
Don't rely on the exact format of the return value because it may change in minor releases.
We will update the documentation if the return value format becomes a supported part of
the public API.
printInclusive() {#printinclusive}
Perf.start()
// ...
Perf.stop()
Perf.getLastMeasurements()
Perf.printInclusive(measurements)
Performance Tools
33
34. Prints the overall time taken. When no arguments are passed, printInclusive defaults to all
the measurements from the last recording. This prints a nicely formatted table in the console,
like so:
printExclusive() {#printexclusive}
"Exclusive" times don't include the times taken to mount the components: processing props, cal-
ling componentWillMount and componentDidMount , etc.
printWasted() {#printwasted}
The most useful part of the profiler.
"Wasted" time is spent on components that didn't actually render anything, e.g. the render stay-
ed the same, so the DOM wasn't touched.
printOperations() {#printoperations}
Prints the underlying DOM manipulations, e.g. "set innerHTML" and "remove".
printDOM() {#printdom}
This method has been renamed to printOperations() . Currently printDOM() still exists as an
alias but it prints a deprecation warning and will eventually be removed.
Perf.printExclusive(measurements)
Perf.printWasted(measurements)
Perf.printOperations(measurements)
Perf.printDOM(measurements)
react
34
35. PureRenderMixin
Note:
PureRenderMixin is a legacy add-on. Use React.PureComponent instead.
Importing
Overview
If your React component's render function renders the same result given the same props and sta-
te, you can use this mixin for a performance boost in some cases.
Example:
Under the hood, the mixin implements shouldComponentUpdate, in which it compares the cur-
rent props and state with the next ones and returns false if the equalities pass.
Note:
This only shallowly compares the objects. If these contain complex data structures, it may
produce false-negatives for deeper differences. Only mix into components which have sim-
ple props and state, or use forceUpdate() when you know deep data structures have
changed. Or, consider using immutable objects to facilitate fast comparisons of nested data.
Furthermore, shouldComponentUpdate skips updates for the whole component subtree.
Make sure all the children components are also "pure".
import PureRenderMixin from 'react-addons-pure-render-mixin'; // ES6
var PureRenderMixin = require('react-addons-pure-render-mixin'); // ES5 with npm
const createReactClass = require('create-react-class');
createReactClass({
mixins: [PureRenderMixin],
render: function() {
return <div className={this.props.className}>foo</div>;
}
});
PureRenderMixin
35
36. Shallow Compare
Note:
shallowCompare is a legacy add-on. Use React.memo or React.PureComponent instead.
Importing
Overview
Before React.PureComponent was introduced, shallowCompare was commonly used to achieve
the same functionality as PureRenderMixin while using ES6 classes with React.
If your React component's render function is "pure" (in other words, it renders the same result
given the same props and state), you can use this helper function for a performance boost in
some cases.
Example:
shallowCompare performs a shallow equality check on the current props and nextProps ob-
jects as well as the current state and nextState objects.
It does this by iterating on the keys of the objects being compared and returning true when the
values of a key in each object are not strictly equal.
shallowCompare returns true if the shallow comparison for props or state fails and therefore
the component should update.
shallowCompare returns false if the shallow comparison for props and state both pass and
therefore the component does not need to update.
import shallowCompare from 'react-addons-shallow-compare'; // ES6
var shallowCompare = require('react-addons-shallow-compare'); // ES5 with npm
export class SampleComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return shallowCompare(this, nextProps, nextState);
}
render() {
return <div className={this.props.className}>foo</div>;
}
}
react
36
37. Shallow Renderer
Import
Übersicht
Beim Schreiben von unit tests kann flaches Rendering (engl. shallow rendering) hilfreich sein.
Flaches Rendering ermöglicht es, eine Komponente "einen Level tief" zu rendern, und vergleicht
den zurückgegebenen Wert der Render Methode, ohne sich über das Verhalten der Kind-Kompo-
nenten, welche nicht instanziiert oder gerendert werden, Sorgen zu machen. Ein DOM wird hier-
bei nicht verlangt.
Wenn du zum Beispiel folgende Komponente hast:
So können wir sie testen:
Flaches Rendering hat derzeit die Einschränkung, dass refs nicht unterstützt werden.
Hinweis:
Wir empfehlen auch, sich die Shallow Rendering API von Enzyme anzusehen. Sie stellt eine
angenehmere übergeordnete API mit den gleichen Funktionalitäten bereit.
import ShallowRenderer from 'react-test-renderer/shallow'; // ES6
var ShallowRenderer = require('react-test-renderer/shallow'); // ES5 mit npm
function MyComponent() {
return (
<div>
<span className="heading">Titel</span>
<Subcomponent foo="bar" />
</div>
);
}
import ShallowRenderer from 'react-test-renderer/shallow';
// in deinem Test:
const renderer = new ShallowRenderer();
renderer.render(<MyComponent />);
const result = renderer.getRenderOutput();
expect(result.type).toBe('div');
expect(result.props.children).toEqual([
<span className="heading">Titel</span>,
<Subcomponent foo="bar" />
]);
Shallow Renderer
37
38. Referenz
shallowRenderer.render() {#shallowrendererrender}
Du kannst dir den shallowRenderer als den "Ort" vorstellen an dem die zu testende Komponente
gerendert wird, und du daraus die Ausgabe der Komponente entnehmen kannst.
shallowRenderer.render() ist ähnlich wie root.render() , nur dass es kein DOM benötigt
und nur einen Level tief rendert. Das bedeutet, dass du Komponenten abgegrenzt testen kannst,
unabhängig davon wie die Kind-Komponenten implementiert sind.
shallowRenderer.getRenderOutput()
{#shallowrenderergetrenderoutput}
Nachdem shallowRenderer.render() aufgerufen wurde, kannst du dir mit shallowRenderer‐
.getRenderOutput() die flach gerenderte Ausgabe zurückgeben lassen.
Dann kann man anfangen, die Ausgabe zu testen.
react
38
39. Test-Utilities
Import
Übersicht
ReactTestUtils bieten eine einfache Möglichkeit, React-Komponenten in einem Test-Framework
deiner Wahl zu testen. Bei Facebook benutzen wir Jest für schmerzfreie Javascript-Tests. Du
kannst das React-Tutorial auf Jest's Webseite besuchen, um Jest zu lernen.
Hinweis:
Wir empfehlen die Verwendung der React Testing Library, die konzipiert wurde, um das
Schreiben von Tests zu ermöglichen, in denen Komponenten auf die gleiche Weise verwen-
det werden wie von Endnutzern.
Für React-Versionen <= 16 macht es die Enzyme Bibliothek einfach, die Ausgabe deiner
React-Komponenten zu prüfen, zu manipulieren und zu durchlaufen.
act()
mockComponent()
isElement()
isElementOfType()
isDOMComponent()
isCompositeComponent()
isCompositeComponentWithType()
findAllInRenderedTree()
scryRenderedDOMComponentsWithClass()
findRenderedDOMComponentWithClass()
scryRenderedDOMComponentsWithTag()
findRenderedDOMComponentWithTag()
scryRenderedComponentsWithType()
findRenderedComponentWithType()
renderIntoDocument()
Simulate
import ReactTestUtils from 'react-dom/test-utils'; // ES6
var ReactTestUtils = require('react-dom/test-utils'); // ES5 mit npm
Test-Utilities
39
40. Referenz
act() {#act}
Um eine Komponente für Assertionen vorzubereiten, setze den Code, der sie rendert und aktuali-
siert, in einen act() -Aufruf. Damit läuft der Test so ähnlich ab, wie React auch im Browser
funktioniert.
Hinweis
Falls du react-test-renderer verwendest, kannst du dessen act -Export verwenden,
der sich gleich verhält.
Stelle dir als Beispiel vor, du hast diese Counter -Komponente:
So können wir sie testen:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: 0};
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
document.title = `Du hast ${this.state.count} Mal geklickt`;
}
componentDidUpdate() {
document.title = `Du hast ${this.state.count} Mal geklickt`;
}
handleClick() {
this.setState(state => ({
count: state.count + 1,
}));
}
render() {
return (
<div>
<p>Du hast {this.state.count} Mal geklickt</p>
<button onClick={this.handleClick}>
Klick mich
</button>
</div>
);
}
}
import React from 'react';
import ReactDOM from 'react-dom/client';
import { act } from 'react-dom/test-utils';
import Counter from './Counter';
let container;
beforeEach(() => {
react
40
41. Vergiss nicht, dass das Abschicken von DOM-Events nur funktioniert, wenn der DOM-Container
zum document hinzugefügt wurde. Du kannst React Testing Library zur Hilfe nehmen,
um Boilerplate-Code zu reduzieren.
Das recipes Dokument enthält mehr Details dazu, wie sich act() verhält, mit Beispiele und
Anwendungsgebieten.
mockComponent() {#mockcomponent}
Übergebe dieser Methode ein gemocktes Komponenten-Modul, um es mit nützlichen Methoden zu
erweitern, mit denen es als Dummy-React-Komponente verwendet werden kann. Anstatt wie üb-
lich zu rendern, wird die Komponente zu einem einfachen <div> (oder zu einem anderen Tag ,
falls mockTagName angegeben wurde), das die ihr übergegebenen Children-Elemente enthält.
Hinweis:
mockComponent() ist eine veraltete API. Wir empfehlen, stattdessen jest.mock() zu
verwenden.
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
it('kann einen Counter rendern und updaten', () => {
// Erstes Rendern und componentDidMount testen
act(() => {
ReactDOM.createRoot(container).render(<Counter />);
});
const button = container.querySelector('button');
const label = container.querySelector('p');
expect(label.textContent).toBe('Du hast 0 Mal geklickt');
expect(document.title).toBe('Du hast 0 Mal geklickt');
// Zweites Rendern und componentDidUpdate testen
act(() => {
button.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(label.textContent).toBe('Du hast 1 Mal geklickt');
expect(document.title).toBe('Du hast 1 Mal geklickt');
});
mockComponent(
componentClass,
[mockTagName]
)
Test-Utilities
41
42. isElement() {#iselement}
Gibt true zurück, falls element ein React-Element ist.
isElementOfType() {#iselementoftype}
Gibt true zurück, falls element ein React-Element vom Typ React componentClass ist.
isDOMComponent() {#isdomcomponent}
Gibt true zurück, falls instance eine DOM-Komponente (z. B. ein <div> oder <span> ) ist.
isCompositeComponent() {#iscompositecomponent}
Gibt true zurück, falls instance eine benutzerdefinierte Komponente, z. B. eine Klasse oder
Funktion, ist.
isCompositeComponentWithType()
{#iscompositecomponentwithtype}
Gibt true zurück, falls instance eine Komponente vom Typ React componentClass ist.
findAllInRenderedTree() {#findallinrenderedtree}
isElement(element)
isElementOfType(
element,
componentClass
)
isDOMComponent(instance)
isCompositeComponent(instance)
isCompositeComponentWithType(
instance,
componentClass
)
findAllInRenderedTree(
tree,
test
)
react
42
43. Durchläuft alle Komponenten in tree und sammelt alle Komponenten, bei denen test(compo‐
nent) true ist. Das ist für sich allein genommen nicht besonders nützlich, wird aber als Primiti-
ve für andere Test-Utilities verwendet.
scryRenderedDOMComponentsWithClass()
{#scryrendereddomcomponentswithclass}
Findet alle DOM-Elemente von Komponenten im gerenderten Baum, bei denen der Klassennamen
der Komponenten mit className übereinstimmt.
findRenderedDOMComponentWithClass()
{#findrendereddomcomponentwithclass}
Verhält sich wie scryRenderedDOMComponentsWithClass() , erwartet aber genau ein Resultat
und gibt dieses zurück. Gibt einen Fehler aus, falls es mehr oder weniger als eine Übereinstim-
mung gibt.
scryRenderedDOMComponentsWithTag()
{#scryrendereddomcomponentswithtag}
Findet alle DOM-Elemente von Komponenten im gerenderten Baum, bei denen der Tagname der
Komponenten mit tagName übereinstimmt.
findRenderedDOMComponentWithTag()
{#findrendereddomcomponentwithtag}
scryRenderedDOMComponentsWithClass(
tree,
className
)
findRenderedDOMComponentWithClass(
tree,
className
)
scryRenderedDOMComponentsWithTag(
tree,
tagName
)
findRenderedDOMComponentWithTag(
tree,
tagName
)
Test-Utilities
43
44. Verhält sich wie scryRenderedDOMComponentsWithTag() , erwartet aber genau ein Resultat und
gibt dieses zurück. Gibt einen Fehler aus, falls es mehr oder weniger als eine Übereinstimmung
gibt.
scryRenderedComponentsWithType()
{#scryrenderedcomponentswithtype}
Findet alle Instanzen von Komponenten, deren Typ mit componentClass übereinstimmt.
findRenderedComponentWithType()
{#findrenderedcomponentwithtype}
Verhält sich wie scryRenderedComponentsWithType() , erwartet aber genau ein Resultat und
gibt dieses zurück. Gibt einen Fehler aus, falls es mehr oder weniger als eine Übereinstimmung
gibt.
renderIntoDocument() {#renderintodocument}
Rendert ein React-Element in einen separaten DOM-Knoten im Dokument. Diese Funktion be-
nötigt ein DOM. Effektiv ist sie äquivalent zu:
Hinweis:
window , window.document und window.document.createElement müssen global ver-
fügbar sein, bevor du React importierst. Ansonsten denkt React, dass es nicht auf das
DOM zugreifen kann, und Methoden wie setState werden nicht funktionieren.
scryRenderedComponentsWithType(
tree,
componentClass
)
findRenderedComponentWithType(
tree,
componentClass
)
renderIntoDocument(element)
const domContainer = document.createElement('div');
ReactDOM.createRoot(domContainer).render(element);
react
44
45. Andere Utilities
Simulate {#simulate}
Simuliere das Abschicken eines Events auf einen DOM-Knoten mit optionalen eventData -
Eventdaten.
Simulate hat eine Methode für jedes Event, das React versteht.
Ein Element anklicken
Den Wert eines Input-Feldes verändern und dann ENTER drücken
Hinweis
Du musst jede Event-Eigenschaft angeben, die du in deiner Komponente verwendest (z. B.
keyCode, which, etc.), da React keine davon für dich erstellt.
Simulate.{eventName}(
element,
[eventData]
)
// <button ref={(node) => this.button = node}>...</button>
const node = this.button;
ReactTestUtils.Simulate.click(node);
// <input ref={(node) => this.textInput = node} />
const node = this.textInput;
node.value = 'Giraffe';
ReactTestUtils.Simulate.change(node);
ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
Test-Utilities
45
46. Two-way Binding Helpers
Note:
LinkedStateMixin is deprecated as of React v15. The recommendation is to explicitly set
the value and change handler, instead of using LinkedStateMixin .
Importing
Overview
LinkedStateMixin is an easy way to express two-way binding with React.
In React, data flows one way: from owner to child. We think that this makes your app's code ea-
sier to understand. You can think of it as "one-way data binding."
However, there are lots of applications that require you to read some data and flow it back into
your program. For example, when developing forms, you'll often want to update some React
state when you receive user input. Or perhaps you want to perform layout in JavaScript and re-
act to changes in some DOM element size.
In React, you would implement this by listening to a "change" event, read from your data source
(usually the DOM) and call setState() on one of your components. "Closing the data flow loop"
explicitly leads to more understandable and easier-to-maintain programs. See our forms docu-
mentation for more information.
Two-way binding -- implicitly enforcing that some value in the DOM is always consistent with
some React state -- is concise and supports a wide variety of applications. We've provided
LinkedStateMixin : syntactic sugar for setting up the common data flow loop pattern described
above, or "linking" some data source to React state .
Note:
LinkedStateMixin is just a thin wrapper and convention around the onChange / setSta‐
te() pattern. It doesn't fundamentally change how data flows in your React application.
LinkedStateMixin: Before and After
Here's a simple form example without using LinkedStateMixin :
import LinkedStateMixin from 'react-addons-linked-state-mixin'; // ES6
var LinkedStateMixin = require('react-addons-linked-state-mixin'); // ES5 with npm
react
46
47. This works really well and it's very clear how data is flowing, however, with a lot of form fields it
could get a bit verbose. Let's use LinkedStateMixin to save us some typing:
LinkedStateMixin adds a method to your React component called linkState() .
linkState() returns a valueLink object which contains the current value of the React state
and a callback to change it.
valueLink objects can be passed up and down the tree as props, so it's easy (and explicit) to
set up two-way binding between a component deep in the hierarchy and state that lives higher in
the hierarchy.
Note that checkboxes have a special behavior regarding their value attribute, which is the value
that will be sent on form submit if the checkbox is checked (defaults to on ). The value attribu-
te is not updated when the checkbox is checked or unchecked. For checkboxes, you should use
checkedLink instead of valueLink :
Under the Hood
There are two sides to LinkedStateMixin : the place where you create the valueLink instance
and the place where you use it. To prove how simple LinkedStateMixin is, let's rewrite each
side separately to be more explicit.
var createReactClass = require('create-react-class');
var NoLink = createReactClass({
getInitialState: function() {
return {message: 'Hello!'};
},
handleChange: function(event) {
this.setState({message: event.target.value});
},
render: function() {
var message = this.state.message;
return <input type="text" value={message} onChange={this.handleChange} />;
}
});
var createReactClass = require('create-react-class');
var WithLink = createReactClass({
mixins: [LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function() {
return <input type="text" valueLink={this.linkState('message')} />;
}
});
<input type="checkbox" checkedLink={this.linkState('booleanValue')} />
Two-way Binding Helpers
47
48. valueLink Without LinkedStateMixin
As you can see, valueLink objects are very simple objects that just have a value and re‐
questChange prop. And LinkedStateMixin is similarly simple: it just populates those fields
with a value from this.state and a callback that calls this.setState() .
LinkedStateMixin Without valueLink
The valueLink prop is also quite simple. It simply handles the onChange event and calls
this.props.valueLink.requestChange() and also uses this.props.valueLink.value ins-
tead of this.props.value . That's it!
var createReactClass = require('create-react-class');
var WithoutMixin = createReactClass({
getInitialState: function() {
return {message: 'Hello!'};
},
handleChange: function(newValue) {
this.setState({message: newValue});
},
render: function() {
var valueLink = {
value: this.state.message,
requestChange: this.handleChange
};
return <input type="text" valueLink={valueLink} />;
}
});
var LinkedStateMixin = require('react-addons-linked-state-mixin');
var createReactClass = require('create-react-class');
var WithoutLink = createReactClass({
mixins: [LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function() {
var valueLink = this.linkState('message');
var handleChange = function(e) {
valueLink.requestChange(e.target.value);
};
return <input type="text" value={valueLink.value} onChange={handleChange} />;
}
});
react
48
49. Immutability Helpers
Note:
update is a legacy add-on. Use immutability-helper instead.
Importing
Overview
React lets you use whatever style of data management you want, including mutation. However, if
you can use immutable data in performance-critical parts of your application it's easy to imple-
ment a fast shouldComponentUpdate() method to significantly speed up your app.
Dealing with immutable data in JavaScript is more difficult than in languages designed for it, like
Clojure. However, we've provided a simple immutability helper, update() , that makes dealing
with this type of data much easier, without fundamentally changing how your data is represented.
You can also take a look at Facebook's Immutable-js and the Advanced Performance section for
more detail on Immutable-js.
The Main Idea
If you mutate data like this:
You have no way of determining which data has changed since the previous copy has been over-
written. Instead, you need to create a new copy of myData and change only the parts of it that
need to be changed. Then you can compare the old copy of myData with the new one in
shouldComponentUpdate() using triple-equals:
Unfortunately, deep copies are expensive, and sometimes impossible. You can alleviate this by
only copying objects that need to be changed and by reusing the objects that haven't changed.
Unfortunately, in today's JavaScript this can be cumbersome:
import update from 'react-addons-update'; // ES6
var update = require('react-addons-update'); // ES5 with npm
myData.x.y.z = 7;
// or...
myData.a.b.push(9);
const newData = deepCopy(myData);
newData.x.y.z = 7;
newData.a.b.push(9);
Immutability Helpers
49
50. While this is fairly performant (since it only makes a shallow copy of log n objects and reuses
the rest), it's a big pain to write. Look at all the repetition! This is not only annoying, but also
provides a large surface area for bugs.
update() {#update}
update() provides simple syntactic sugar around this pattern to make writing this code easier.
This code becomes:
While the syntax takes a little getting used to (though it's inspired by MongoDB's query
language) there's no redundancy, it's statically analyzable and it's not much more typing than the
mutative version.
The $ -prefixed keys are called commands. The data structure they are "mutating" is called the
target.
Available Commands
{$push: array} push() all the items in array on the target.
{$unshift: array} unshift() all the items in array on the target.
{$splice: array of arrays} for each item in arrays call splice() on the target with
the parameters provided by the item.
{$set: any} replace the target entirely.
{$merge: object} merge the keys of object with the target.
{$apply: function} passes in the current value to the function and updates it with the new
returned value.
Examples
Simple push
initialArray is still [1, 2, 3] .
const newData = extend(myData, {
x: extend(myData.x, {
y: extend(myData.x.y, {z: 7}),
}),
a: extend(myData.a, {b: myData.a.b.concat(9)})
});
import update from 'react-addons-update';
const newData = update(myData, {
x: {y: {z: {$set: 7}}},
a: {b: {$push: [9]}}
});
const initialArray = [1, 2, 3];
const newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
react
50
51. Nested collections
This accesses collection 's index 2 , key a , and does a splice of one item starting from index
1 (to remove 17 ) while inserting 13 and 14 .
Updating a value based on its current one
(Shallow) Merge
const collection = [1, 2, {a: [12, 17, 15]}];
const newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
// => [1, 2, {a: [12, 13, 14, 15]}]
const obj = {a: 5, b: 3};
const newObj = update(obj, {b: {$apply: function(x) {return x * 2;}}});
// => {a: 5, b: 6}
// This is equivalent, but gets verbose for deeply nested collections:
const newObj2 = update(obj, {b: {$set: obj.b * 2}});
const obj = {a: 5, b: 3};
const newObj = update(obj, {$merge: {b: 6, c: 7}}); // => {a: 5, b: 6, c: 7}
Immutability Helpers
51
52. Add-Ons
Hinweis:
React.addons ist seit React v15.5 veraltet. Die Add-Ons sind in ein separates Modul ver-
schoben worden und einige von ihnen nicht mehr dem neusten Stand.
React Add-Ons sind eine Ansammlung von nützlichen Modulen für das Erstellen von React-Apps.
Sie sollten aber als "experimentell" betrachtet werden, da es sein kann, dass sie sich häu-
figer als React-Core ändern.
createFragment , um eine Menge von mit Schlüssel versehenden Kind-Elementen zu
erstellen.
Die unten stehenden Add-Ons sind nur in der Entwicklungsversion (nicht minimiert und optimiert)
von React integriert:
Perf , ein Tool um Optimierungsmöglickeiten in der Performance zu finden.
ReactTestUtils , kleine einfache Hilfsmittel zum Schreiben von Tests.
Add-on Altlasten
Die unten stehenden Add-Ons gelten als Altlasten aus vorherigen Versionen. Sie werden wahr-
scheinlich noch in zukünftigen React-Versionen funktionieren, aber nicht mehr aktiv
weiterentwickelt.
PureRenderMixin . Benutze stattdessen React.PureComponent .
shallowCompare , eine Hilfsfunktion, die dich durch das oberflächliche Vergleichen von props
und states entscheiden lässt, ob eine Komponente aktualisiert werden soll oder nicht. Wir
empfehlen dir aber stattdessen lieber React.PureComponent zu benutzen.
update . Benutze stattdessen kolodny/immutability-helper .
ReactDOMFactories , vorkonfigurierte DOM-Factories um es einfacher zu machen, React ohne
JSX zu verwenden.
Veraltete Add-Ons
LinkedStateMixin ist veraltet.
TransitionGroup und CSSTransitionGroup sind veraltet, da sie durch ein Modul der Com-
munity ersetzt worden sind.
React mit Add-Ons verwenden
Du kannst die Add-Ons einzeln über npm (z. B. npm install react-addons-create-fragment )
installieren und importieren:
react
52
53. Du kannst react-with-addons.js anstelle von react.js benutzen, wenn du React 15 oder ei-
ner frühere Version über ein CDN beziehst.
Die Add-Ons werden über React.addons global verfügbar sein (z. B.
React.addons.TestUtils ).
import createFragment from 'react-addons-create-fragment'; // ES6
var createFragment = require('react-addons-create-fragment'); // ES5 mit npm
<script src="https://unpkg.com/react@15/dist/react-with-addons.js"></script>
Add-Ons
53
54. CDN Links
React und ReactDOM sind beide über CDNs verfügbar.
Diese beiden Versionen sind nur zu Entwicklung angedacht und nicht für den Live-Einsatz in Pro-
duktivsystemen. Für diesen Gebrauch haben wir extra verkleinerte und optimierte Versionen von
React bereitgestellt:
Ersetze 18 mit einer gültigen Versionsnummer um eine bestimmte Version von react oder re‐
act-dom zu laden.
Warum das crossorigin Attribut?
Wir empfehlen dir, wenn du React von einem CDN beziehst, dass du das crossorigin gesetzt
lässt oder setzt:
Wir empfehlen außerdem zu überprüfen ob das verwendete CDN den Access-Control-Allow-
Origin: * HTTP header gesetzt hat:
Access-Control-Allow-Origin: *
Dies ermöglicht dir ab React 16 eine bessere Fehlerbehandlung.
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></scrip
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></sc
<script crossorigin src="..."></script>
react
54
55. Code-Aufteilung
Bundling
Die meisten React Anwendungen werden ihre Dateien durch Tools wie Webpack, Rollup oder
Browserify zusammengeführt haben. Bundling nennt sich der Prozess, in dem importierte Dateien
zu einer Datei zusammengefügt werden: ein "Bündel (engl. bundle)". Dieses Bundle kann dann in
eine Webseite eingebettet werden um eine komplette Anwendung auf einmal zu laden.
Beispiel
App:
Bündel:
Hinweis:
Deine Bundles werden am Ende ganz anders aussehen als das hier.
Wenn du Create React App, Next.js, Gatsby, oder ein ähnliches Tool benutzt, wirst du ein Web-
pack-Setup haben welches sofort einsatzbereit ist um deine Anwendung zu bundlen.
Wenn nicht, musst du das Bundling selbst einrichten. Siehe z. B. die Abschnitte Installation und
Erste Schritte in der Webpack-Dokumentation.
Code-Splitting
Bundling ist großartig, aber sobald deine Anwendung wächst, wird dein Bundle es auch. Insbe-
sondere wenn du größere Bibliotheken von Drittanbietern einbeziehst. Du musst ein Auge auf den
Code haben, den du im Bundle hast, damit du ihn nicht versehentlich so groß machst und deine
Anwendung zu lange zum Laden benötigt.
// app.js
import { add } from './math.js';
console.log(add(16, 26)); // 42
// math.js
export function add(a, b) {
return a + b;
}
function add(a, b) {
return a + b;
}
console.log(add(16, 26)); // 42
Code-Aufteilung
55
56. Um zu vermeiden, dass du mit einem großen Bundle endest, ist es gut, dem Problem voraus zu
sein und mit dem "Splitten" (dt. aufteilen) deines Bundles zu beginnen. Code-Splitting ist eine
Funktion, die von Bundlern wie Webpack, Rollup und Browserify unterstützt wird (via factor-
bundle). Durch sie werden mehrere Bundles erzeugt, die zur Laufzeit dynamisch geladen werden
können.
Code-Splitting deiner Anwendung kann dir helfen genau die Dinge "lazy zu laden", die der Benut-
zer gerade benötigt, was die Performance deiner Anwendung drastisch verbessern kann. Du hast
zwar die Gesamtmenge an Code nicht verringert, aber du hast das Laden von Code vermieden,
den der Benutzer möglicherweise nie brauchen wird. Zusätzlich reduzierst du die Menge an Code
beim initialen Laden.
import() {#import}
Der beste Weg Code-Splitting in deiner Anwendung einzuführen, ist durch die dynamische im‐
port() -Syntax.
Vorher:
Nachher:
Wenn Webpack auf diese Syntax stößt, fängt es automatisch mit dem Code-Splitting deiner An-
wendung an. Wenn du Create-React-App verwendest, ist dies alles vorkonfiguriert und du kannst
[direkt loslegen]((https://create-react-app.dev/docs/code-splitting/). Next.js unterstützt dies
auch direkt out of the box.
Wenn du Webpack selbst einrichtest, wirst du wahrschenlich Webpack's Code-Splitting Leitfaden
lesen wollen. Deine Webpack-Konfiguration sollte in etwa so aussehen.
Wenn du Babel verwendest, müsstest du sicherstellen, dass Babel die Dynamic-Import-Syntax
parsen kann, sie aber nicht transformiert. Für all das benötigst du @babel/plugin-syntax-dyna-
mic-import.
React.lazy {#reactlazy}
Mit der Funktion React.lazy kannst du einen dynamischen Import als reguläre Komponente
rendern.
Before:
import { add } from './math';
console.log(add(16, 26));
import("./math").then(math => {
console.log(math.add(16, 26));
});
import OtherComponent from './OtherComponent';
react
56
57. After:
Dadurch wird automatisch das Bundle geladen, dass OtherComponent enthält, wenn die Kompo-
nente das erste Mal gerendert wird.
React.lazy nimmt eine Funktion entgegen, die ein dynamisches import() aufrufen muss.
Dies muss ein Promise zurückgeben, welches eine Modul auflöst, dass eine React-Komponenten
im default Export enthält.
Die Lazy-Komponente sollte dann in einer Suspense -Komponente gerendert werden, was es uns
ermöglicht ein wenig Fallback-Inhalt anzuzeigen (z. B. eine Ladeanzeige), während wir darauf
warten, dass die Lazy-Komponente lädt.
Das fallback -Prop akzeptiert jedes React-Element, das du rendern möchtest, während du drauf
wartest, dass die Komponente geladen wird. Du kannst die Suspense -Komponente überall über
der Lazy-Komponente platzieren. Du kannst sogar mehrere Lazy-Komponenten mit einer einzigen
Suspense -Komponente umhüllen.
const OtherComponent = React.lazy(() => import('./OtherComponent'));
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</div>
);
}
Code-Aufteilung
57
58. Avoiding fallbacks
Any component may suspend as a result of rendering, even components that were already shown
to the user. In order for screen content to always be consistent, if an already shown component
suspends, React has to hide its tree up to the closest <Suspense> boundary. However, from the
user's perspective, this can be disorienting.
Consider this tab switcher:
In this example, if tab gets changed from 'photos' to 'comments' , but Comments suspends,
the user will see a glimmer. This makes sense because the user no longer wants to see Photos ,
the Comments component is not ready to render anything, and React needs to keep the user ex-
perience consistent, so it has no choice but to show the Glimmer above.
However, sometimes this user experience is not desirable. In particular, it is sometimes better to
show the "old" UI while the new UI is being prepared. You can use the new startTransition
API to make React do this:
Here, you tell React that setting tab to 'comments' is not an urgent update, but is a transition
that may take some time. React will then keep the old UI in place and interactive, and will switch
to showing <Comments /> when it is ready. See Transitions for more info.
import React, { Suspense } from 'react';
import Tabs from './Tabs';
import Glimmer from './Glimmer';
const Comments = React.lazy(() => import('./Comments'));
const Photos = React.lazy(() => import('./Photos'));
function MyComponent() {
const [tab, setTab] = React.useState('photos');
function handleTabSelect(tab) {
setTab(tab);
};
return (
<div>
<Tabs onTabSelect={handleTabSelect} />
<Suspense fallback={<Glimmer />}>
{tab === 'photos' ? <Photos /> : <Comments />}
</Suspense>
</div>
);
}
function handleTabSelect(tab) {
startTransition(() => {
setTab(tab);
});
}
react
58
59. Fehlergrenzen
Wenn das andere Modul nicht lädt (z. B. aufgrund eines Netzwerkausfalls), löst es einen Fehler
aus. Du kannst diese Fehler behandeln, um eine schönere Benutzererfahrung zu bieten und die
Wiederherstellung mit Fehlergrenzen zu verwalten. Sobald du deine Fehlergrenze erstellt hast,
kannst du sie überall oberhalb deinen Lazy-Komponenten verwenden, um einen Fehlerstatus an-
zuzeigem, wenn ein Netzwerkfehler vorliegt.
Routen basiertes Code-Splitting
Die Entscheidung wo in deiner Anwendung Code-Splitting einzuführen ist, kann etwas schwierig
sein. Du solltest sicherstellen, dass du Orte wählst, die die Bundles gleichmäßig splitten, aber
nicht die Benutzererfahrung beeinträchtigen.
Ein guter Ausgangspunkt sind Routen. Die meisten Leute im Web sind es gewohnt Page-Transiti-
ons zu erstellen, die einige Zeit zum Laden benötigen. Sie neigen auch dazu, die gesamte Seite
auf einmal neu zu rendern, so dass die Benutzer wahrscheinlich nicht gleichzeitig mit anderen
Elementen auf der Seite interagieren.
Hier ist ein Beispiel wie du ein routenbasiertes Code-Splitting in deiner Anwendung mit Hilfe von
Bibliotheken, wie React Router mit React.lazy einrichtest.
import React, { Suspense } from 'react';
import MyErrorBoundary from './MyErrorBoundary';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
const MyComponent = () => (
<div>
<MyErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</MyErrorBoundary>
</div>
);
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<Router>
<Suspense fallback={<div>Lade...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
Code-Aufteilung
59
60. Benannte Exporte
React.lazy unterstützt derzeit nur default Exporte. Wenn das Modul, das du importieren
möchtest, benannte exports enthält, kannst du ein Zwischenmodul erstellen, das es als de‐
fault wieder exportiert. Dies stellt sicher, dass das Tree-Shaking weiter funktioniert und es kei-
ne unbenutzten Komponenten mit einbezieht.
</Suspense>
</Router>
);
// ManyComponents.js
export const MyComponent = /* ... */;
export const MyUnusedComponent = /* ... */;
// MyComponent.js
export { MyComponent as default } from "./ManyComponents.js";
// MyApp.js
import React, { lazy } from 'react';
const MyComponent = lazy(() => import("./MyComponent.js"));
react
60
61. Codebase Overview
This section will give you an overview of the React codebase organization, its conventions, and
the implementation.
If you want to contribute to React we hope that this guide will help you feel more comfortable
making changes.
We don't necessarily recommend any of these conventions in React apps. Many of them exist for
historical reasons and might change with time.
Top-Level Folders
After cloning the React repository, you will see a few top-level folders in it:
packages contains metadata (such as package.json ) and the source code ( src subdirec-
tory) for all packages in the React repository. If your change is related to the code, the
src subdirectory of each package is where you'll spend most of your time.
fixtures contains a few small React test applications for contributors.
build is the build output of React. It is not in the repository but it will appear in your React
clone after you build it for the first time.
The documentation is hosted in a separate repository from React.
There are a few other top-level folders but they are mostly used for the tooling and you likely
won't ever encounter them when contributing.
Colocated Tests
We don't have a top-level directory for unit tests. Instead, we put them into a directory called
__tests__ relative to the files that they test.
For example, a test for setInnerHTML.js is located in __tests__/setInnerHTML-test.js
right next to it.
Warnings and Invariants
The React codebase uses console.error to display warnings:
Warnings are only enabled in development. In production, they are completely stripped out. If
you need to forbid some code path from executing, use invariant module instead:
if (__DEV__) {
console.error('Something is wrong.');
}
var invariant = require('invariant');
invariant(
Codebase Overview
61
62. The invariant is thrown when the invariant condition is false .
"Invariant" is just a way of saying "this condition always holds true". You can think about it as
making an assertion.
It is important to keep development and production behavior similar, so invariant throws both
in development and in production. The error messages are automatically replaced with error
codes in production to avoid negatively affecting the byte size.
Development and Production
You can use __DEV__ pseudo-global variable in the codebase to guard development-only blocks
of code.
It is inlined during the compile step, and turns into process.env.NODE_ENV !== 'production'
checks in the CommonJS builds.
For standalone builds, it becomes true in the unminified build, and gets completely stripped out
with the if blocks it guards in the minified build.
Flow
We recently started introducing Flow checks to the codebase. Files marked with the @flow anno-
tation in the license header comment are being typechecked.
We accept pull requests adding Flow annotations to existing code. Flow annotations look like this:
When possible, new code should use Flow annotations. You can run yarn flow locally to check
your code with Flow.
Multiple Packages
React is a monorepo. Its repository contains multiple separate packages so that their changes
can be coordinated together, and issues live in one place.
2 + 2 === 4,
'You shall not pass!'
);
if (__DEV__) {
// This code will only run in development.
}
ReactRef.detachRefs = function(
instance: ReactInstance,
element: ReactElement | string | number | null | false,
): void {
// ...
}
react
62
63. React Core
The "core" of React includes all the top-level React APIs, for example:
React.createElement()
React.Component
React.Children
React core only includes the APIs necessary to define components. It does not include the
reconciliation algorithm or any platform-specific code. It is used both by React DOM and React
Native components.
The code for React core is located in packages/react in the source tree. It is available on npm
as the react package. The corresponding standalone browser build is called react.js , and it
exports a global called React .
Renderers
React was originally created for the DOM but it was later adapted to also support native platforms
with React Native. This introduced the concept of "renderers" to React internals.
Renderers manage how a React tree turns into the underlying platform calls.
Renderers are also located in packages/ :
React DOM Renderer renders React components to the DOM. It implements top-level React‐
DOM APIs and is available as react-dom npm package. It can also be used as standalone
browser bundle called react-dom.js that exports a ReactDOM global.
React Native Renderer renders React components to native views. It is used internally by Re-
act Native.
React Test Renderer renders React components to JSON trees. It is used by the Snapshot Tes-
ting feature of Jest and is available as react-test-renderer npm package.
The only other officially supported renderer is react-art . It used to be in a separate GitHub re-
pository but we moved it into the main source tree for now.
Note:
Technically the react-native-renderer is a very thin layer that teaches React to interact
with React Native implementation. The real platform-specific code managing the native
views lives in the React Native repository together with its components.
Reconcilers
Even vastly different renderers like React DOM and React Native need to share a lot of logic. In
particular, the reconciliation algorithm should be as similar as possible so that declarative rende-
ring, custom components, state, lifecycle methods, and refs work consistently across platforms.
Codebase Overview
63
64. To solve this, different renderers share some code between them. We call this part of React a "re-
conciler". When an update such as setState() is scheduled, the reconciler calls render() on
components in the tree and mounts, updates, or unmounts them.
Reconcilers are not packaged separately because they currently have no public API. Instead, they
are exclusively used by renderers such as React DOM and React Native.
Stack Reconciler
The "stack" reconciler is the implementation powering React 15 and earlier. We have since stop-
ped using it, but it is documented in detail in the next section.
Fiber Reconciler
The "fiber" reconciler is a new effort aiming to resolve the problems inherent in the stack reconci-
ler and fix a few long-standing issues. It has been the default reconciler since React 16.
Its main goals are:
Ability to split interruptible work in chunks.
Ability to prioritize, rebase and reuse work in progress.
Ability to yield back and forth between parents and children to support layout in React.
Ability to return multiple elements from render() .
Better support for error boundaries.
You can read more about React Fiber Architecture here and here. While it has shipped with React
16, the async features are not enabled by default yet.
Its source code is located in packages/react-reconciler .
Event System
React implements a layer over native events to smooth out cross-browser differences. Its source
code is located in packages/react-dom/src/events .
What Next?
Read the next section to learn about the pre-React 16 implementation of reconciler in more de-
tail. We haven't documented the internals of the new reconciler yet.
react
64
65. Komponenten und Props
Komponenten erlauben dir deine Benutzeroberfläche in unabhängige, wiederverwendbare Teile
aufzubrechen und jeden als isoliert zu betrachten. Diese Seite bietet dir eine Einführung in die
Idee hinter Komponenten. Du kannst eine detailierte Komponentenbeschreibung in der API Refe-
renz finden.
Vom Konzept her sind Komponenten wie JavaScript-Funktionen. Sie akzeptieren beliebige Einga-
ben ("props" genannnt) und geben React-Elemente zurück, welche beschreiben was auf dem
Bildschirm angezeigt werden soll.
Funktions- und Klassenkomponenten
Der einfachste Weg eine Komponente zu definieren, ist eine JavaScript-Funktion zu schreiben:
Diese Funktion ist eine gültige React-Komponente, da sie ein einziges "props"- (engl. kurz für
properties) Objekt mit Daten akzeptiert und ein React-Element zurückgibt. Wir nennen dies
"Funktionskomponenten", weil es buchstäblich JavaScript-Funktionen sind.
Du kannst ebenfalls ES6-Klassen benutzen um Komponenten zu definieren:
Die beiden obigen Komponenten sind aus der Sicht von React identisch.
Funktion- und Klassen-Komponenten haben beide noch ein paar zusätzliche Eigenschaften, wel-
che wir im nächsten Abschnitt besprechen.
Eine Komponente rendern
Bis jetzt haben wir nur React-Elemente kennengelernt, die DOM-Tags repräsentiert haben:
Elemente können aber auch benutzerdefinierte Komponenten darstellen:
React übergibt, wenn es ein Element als benutzerdefinierte Komponente erkennt, alle JSX Attri-
bute als ein einziges Objekt. Dies sind die sogenannten "props" (Eigenschaften).
function Welcome(props) {
return <h1>Hallo {props.name}</h1>;
}
class Welcome extends React.Component {
render() {
return <h1>Hallo {this.props.name}</h1>;
}
}
const element = <div />;
const element = <Welcome name="Sara" />;
Komponenten und Props
65
66. Zum Beispiel rendert dieser Code "Hallo Sarah" auf die Seite:
Auf CodePen ausprobieren
Fassen wir mal zusammen, was in diesem Beispiel passiert:
1. Wir rufen root.render() mit dem React-Element <Welcome name="Sara" /> auf.
2. React ruft die Welcome Komponente mit den Props {name: 'Sara'} auf.
3. Unsere Welcome -Komponente gibt als Ergebnis <h1>Hallo Sara</h1> zurück.
4. React aktualsiert effizient das DOM um <h1>Hallo Sara</h1> abzugleichen.
Hinweis: Beginne den Namen von Komponenten immer mit einem Großbuchstaben.
React behandelt Komponenten, die mit Kleinbuchstaben beginnen, als DOM-Tags. Zum Bei-
spiel stellt <div /> ein HTML div-Tag dar, <Welcome /> hingegen ist eine Komponente
und erfordert, dass Welcome im Scope ist.
Bitte lese JSX im Detail, um mehr über diese Konvention zu erfahren.
Komponenten zusammensetzen
Komponenten können bei ihrer Ausgabe auf andere Komponenten verweisen. So können wir für
jedes Detaillevel die selben abstrahierten Komponenten wiederverwenden. Denn sowohl Buttons,
Formulare als auch Screens, werden in React-Apps allgemein als Komponenten bezeichnet.
Zum Beispiel können wir die App Komponente mehrmals Welcome rendern lassen:
Auf CodePen ausprobieren
function Welcome(props) {
return <h1>Hallo {props.name}</h1>;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
const element = <Welcome name="Sara" />;
root.render(element);
function Welcome(props) {
return <h1>Hallo {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
react
66
67. Typischerweise haben neue React-Apps eine einzige App Komponente an erste Stelle. Wenn du
aber React in ein bestehendes Projekt integrierst, fängst du wahrscheinlich von unten nach oben
(bottom-up) an und erstellst Komponenten wie Button , dabei arbeitest dich Schritt für Schritt
die View-Hierarchie nach oben.
Komponenten auslagern
Hab keine Angst vor dem Aufteilen von Komponenten in kleinere Komponenten.
Nehmen wir mal als Beispiel diese Comment -Komponente:
Auf CodePen ausprobieren
Diese Komponente nimmt author (ein Objekt), text (ein String), und date (ein date-Objekt)
als Props entgegen und beschreibt einen Kommentar auf einer Social Media Webseite.
Aufgrund der Verschachtelung könnte diese Komponente schwer abänderbar sein, außerdem ist
es auch schwierig einzelne Teile davon wiederzuverwenden. Lass uns doch mal ein paar Kompo-
nenten daraus ziehen.
Als erstes werden wir Avatar auslagern:
Der Avatar muss nicht wissen, dass er in innerhalb von Comment gerendert wird. Darum geben
wir dem prop einen gebräuchlicheren namen als: author und nennen es user .
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
Komponenten und Props
67
68. Wir empfehlen props nicht nach dem Kontext in dem sie verwenden werden, sondern aus dem sie
kommen zu benennen.
Wir können nun Comment ein bisschen vereinfachen:
Als nächstes werden wir eine UserInfo Komponente extrahieren, welche einen Avatar neben
den Namen des Benutzers rendert:
Dadurch können wir Comment weiter vereinfachen:
Auf CodePen ausprobieren
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
react
68