Welches JavaScript Framework passt zu mir? – React

Nach dem ersten Post der Blog-Serie “Welches JavaScript Framework passt zu mir?” folgt nun der zweite Post, in dem eine Einführung zu React gegeben wird.

Alle Beiträge dieser Blog-Serie:

Einführung

React ist eine JavaScript-Bibliothek zur Entwicklung von modularen Weboberflächen. Das Projekt wurde von Jordan Walke, einem Softwareentwickler von Facebook, ins Leben gerufen und 2011 das erste Mal für den Facebook Newsfeed verwendet. 2012 wurde React auch für Instagram.com verwendet und 2013 auf der JSConf US unter eine Open Source-Lizenz gestellt. Die Grundidee stammt von XHP, einem HTML-Komponenten-Framework für PHP. Mittlerweile verwenden viele Großfirmen wie Netflix und Airbnb React und helfen zusätzlich bei der Weiterentwicklung von React und der Toollandschaft weiter.
React ist eine reine Oberflächenbibliothek, mit deren Hilfe man modulare Weboberflächen erstellen kann. React unterstützt sowohl server- als auch clientseitiges Rendering.

JSX

Um die Komponentenerstellung zu vereinfachen kann (und sollte) in React JSX eingesetzt werden. JSX ist ein JavaScript Präprozessor, durch den XML innerhalb von JavaScript geschrieben werden kann. In React wird die HTML Struktur meist nicht in extra HTML-Dateien ausgelagert, sondern direkt in die JavaScript-Dateien der Komponenten geschrieben. Setzt man kein JSX ein, können Komponenten über React-Methoden erzeugt werden. Der Vorteil von JSX ist die vereinfachte Lesbarkeit und es lässt sich “einfacher” schreiben, da JSX sehr stark an HTML angelehnt ist.

Ohne JSX

React.createElement(
	MyButton,
	{color: 'blue', shadowSize: 2},
	'Click Me'
);

Mit JSX

<MyButton color="blue" shadowSize={2}>
	Click Me
</MyButton>

Komponenten

In React wird die Oberfläche in viele, möglichst atomare Komponenten unterteilt. Dies dient sowohl der Kapselung, als auch der Wiederverwendbarkeit und der Wartbarkeit. Es wird zwischen zustandslosen und zustandsbehafteten Komponenten unterschieden. Zustandslose Komponenten enthalten keine Logik und dienen ausschließlich der Anzeige, während zustandsbehaftete Komponenten sowohl Logik, als auch Zustand enthalten können und zur Darstellung komplexer Informationen dienen.

Komponenten können als Funktionen oder (dank ECMAScript 6) als Klassen geschrieben werden.

Komponente als Funktion

function HelloWorld() {
    return <h1>Hello World</h1>;
}

Komponenten als Klasse

class HelloWorld extends React.Component {
	render() {
		return <h1>Hello World</h1>;
	}
}

Hierbei ist zu beachten, dass im JavaScript-Code JSX verwendet wird. Daher muss das geschriebene HTML nicht in Anführungszeichen gesetzt werden. Das bietet den Vorteil, dass die Entwicklungsumgebungen das JSX direkt validieren und Syntax highlighting anbieten.

Eigenschaften und Zustand

Komponenten können Eigenschaften und Zustände haben. Eigenschaften werden der Komponente von außen übergeben. Der Zustand wird von der Komponente selbst verwaltet. Sobald entweder die Eigenschaften oder der Zustand verändert wird, wird die Komponente neu gerendert.

Komponentenhierarchien

Es gibt verschiedene Möglichkeiten, Komponenten ineinander zu verschachteln. Die einfachste Variante ist, die verschachtelten Komponenten in der render-Methode der Eltern-Komponente zurückzugeben:

function Title() {
	return <h1>Hello World</h1>;
}

function Header() {
	return <Title />;
}

Eine andere Möglichkeit ist das children-Property, das alle definierten Kind-Komponenten enthält:

function Parent(props) {
	return 
		<span>
			<h1>Parent</h1>
			{this.props.children}
		</span>
}

ReactDOM.render(
	<Parent>
		<Child/>
	</Parent>,
	document.getElementById('root'));

Die Komponente Parent würde somit erst den Titel “Parent” anzeigen und direkt darunter die Child-Komponente.

Event Handling

Eventpropagierung in React


Bei der Initialisierung eines Event Handlers hängt React keinen Event Handler in das DOM. Um auf Events zu reagieren, verwendet React einen globalen Event Handler, der am HTML Element hängt. Dieser globale Event Handler verteilt die Events an die tatsächlichen Event Handler.

Wenn ein Event im DOM ausgeführt wird, steigt das native Event im DOM-Baum bis zum HTML-Element der Seite auf (event bubbling). Hier greift der globale Event Handler von React und erkennt den Ursprung des Events. Anhand dessen wird der zugehörige Event Handler erkannt und das native Event wird – gewrappt in einem React Event – an den Event Handler übergeben. Häufig wird innerhalb dieses Event Handlers der Zustand der Komponente mittels setState bearbeitet. Dieser Aufruf zieht ein erneutes Rendern der Komponente und aller Kind-Komponenten nach sich.

Bei der praktischen Ausführung dieses Eventflusses wird die Anwendung schnell unübersichtlich, weshalb an dieser Stelle meist zu externen Frameworks gegriffen wird. Eines der beliebtesten Frameworks zur Zustands- und Eventverwaltung ist Redux. Redux ist eine Implementierung des FLUX-Architekturpatterns.

Formulare

React verzichtet bewusst auf ein 2-Wege-Databinding, weshalb bei Formularen ein manueller Mechanismus zur Datenverwaltung implementiert werden muss. In sogenannten unkontrollierten Komponenten werden beim Abschicken des Formulars alle Felder auf deren aktuelle Werte abgefragt. In kontrollierten Komponenten wird ein Change-Listener an die Eingabefelder gehängt, und sobald sich ein Wert eines Eingabefeldes ändert, wird der Zustand der Komponenten dem neuen Wert angeglichen. Somit weiß die Komponente zu jedem Zeitpunkt, welchen Inhalt das Formular besitzt.

Routing

Der React Router ist ein Zusatzmodul und De-facto-Standard in React. Mit Hilfe des Routers können Seitennavigationen behandelt, und abhängig von der URL Komponenten angezeigt werden. Ab Version 4 setzt der React Router auf dynamisches Routing. Im Gegensatz zum statischen Routing werden beim dynamischen Routing die URLs (Routes) erst nach und nach definiert. Jede Komponente kann Routes definieren, wodurch je nach Applikationszustand auf unterschiedliche URLs reagiert werden kann.

Der React Router liefert vier verschiedene Router Implementierungen, wobei jede Implementierung ein spezielles Einsatzgebiet hat. Der BrowserRouter nutzt die HTML5 History API und speichert hierin die Navigationshistorie und die aktuelle URL. Der BrowserRouter ist für die meisten Fälle die optimale Wahl. Der HashRouter ändert nur den Location Hash der URL. Somit ändert sich nie die tatsächliche URL, was beispielsweise sinnvoll ist, wenn man eine React Anwendung auf einem simplen HTTP-Server – und nicht wie üblich auf einem Applikationsserver – hosten will. Der MemoryRouter verändert die URL nie. Die Historie wird komplett im Speicher abgelegt und auch dort manipuliert. Dieser Router ist sinnvoll, wenn man sich nicht in einer Browser-Umgebung befindet. Der StaticRouter ist nützlich, wenn die Applikation Server-Side-Rendering benutzt. Der NativeRouter ist ein speziell auf iOS und Android Apps mit React Native ausgelegter Router.

Testen

Facebook hat mit Jest ein Framework geliefert, mit dem sehr einfach React Code getestet werden kann. Jest muss nicht konfiguriert werden und verfügt über Features wie ShallowRendering, Snapshot Testing, Code Coverage Analysen und Mocking. ShallowRendering bietet die Möglichkeit eine Komponente innerhalb einer Sandbox zu rendern. Das heißt, es wird ausschließlich die Komponente gerendert. Die Kind-Komponenten werden außen vor gelassen, um die Komponente atomarer testen zu können und potentielle Fehler in Kind-Komponenten auszuschließen. Mit Snapshot Testing können ungewollte Änderungen an der HTML-Struktur der Komponente erkannt werden. Bei jedem Durchlauf wird der gerenderte HTML Code mit dem HTML Code aus dem vorherigen Testlauf verglichen. Bei Änderungen schlägt der Test fehl und der Entwickler muss angeben, ob es sich um eine gewollte Änderung handelt oder nicht.
Meist wird beim Testen von React Komponenten noch das von Airbnb entwickelte Framework Enzyme eingesetzt, da dessen API sprechender ist. Dies ist allerdings optional.

Short URL for this post: https://wp.me/p4nxik-2VR
This entry was posted in Web as a Platform and tagged , , . Bookmark the permalink.

Leave a Reply