JavaScript: Einführung in React

Aufbau, Syntax und Eigenschaften

Auf der Frontend-Seite besteht React aus Komponenten (Views):

React.renderComponent(
React.DOM.h1(null, 'Hello, world!'),
document.getElementById('example')
);

Mit JSX sieht das Ganze ähnlich aus:

/** @jsx React.DOM */
React.renderComponent(
<h1>Hello, world!</h1>,
document.getElementById('example')
);

Auch wenn das Mischen von JavaScript und HTML auf den ersten Blick etwas seltsam wirkt, schwindet das Gefühl nach kurzer Zeit. Das Trennen des Codes der beiden Sprachen ist im Grunde eine sogenannte Separation of Languages und das Zusammenführen widerspricht nicht dem Prinzip der Separation of Concerns.

Wenn eine Komponente zu groß wird, ist es sinnvoll, sie auf mehrere kleinere, wiederverwendbare Komponenten zu verteilen. Sie sind im Idealfall so klein, dass sie sich gut mit Unit-Tests abdecken lassen sowie eine klare und saubere Struktur der Anwendung ermöglichen.

Auf den ersten Blick sehen React-Komponenten genauso aus wie alltägliches HTML. Dem ist allerdings nicht so, denn es handelt sich lediglich um eine XML-ähnliche Darstellung, die das Entwickeln von JavaScript Renderings angenehmer machen soll.

Attributnamen wie class oder for sind dabei nicht erlaubt. Die Äquivalente className und htmlFor bieten deshalb die Funktionen des HTML-Originals. Diese und weitere Eigenarten der Syntax lassen sich in den JSX Gotchas in der Dokumentation des Projekts nachlesen.

Browser können JSX-Code nicht ausführen, weshalb er in natives JavaScript zu transformieren ist. Ein Vorher-Nachher-Beispiel zeigt den Effekt:

var AComponent;
// Input (JSX):
var app = <AComponent text="Hello" />;
// Output (JS):
var app = React.createElement(AComponent, {text:"Hello"});

Komponenten lassen sich mit dem Befehl React.createClass erstellen. Ihnen ist eine Objektspezifikation zu übergeben, die neben vielen optionalen Methoden für das Verhalten mit der render-Methode eine einzige Pflichtangabe enthält:

var AComponent = React.createClass({
render: function(){
return (
<h1>Hello, world!</h1>
);
}
});

Anschließend kann man die Methode in ein beliebiges DOM-Element rendern:

React.renderComponent(
<AComponent/>,
document.getElementById('example')
);

Anwendungen, die komplett aus React gestrickt sind, werden diese Methode nur ein einziges Mal für die Hauptkomponente aufrufen. Alle restlichen Komponenten wie Header, Navigation, Footer und Content sind in der Hauptkomponente gekapselt.

Um etwas Anzeigelogik einzubauen, kann die Elternkomponente sogenannte props (Properties) weitergeben. In den Child-Komponenten stehen die Eigenschaften mit dem Aufruf von this.props zur Verfügung:

var DayComponent = React.createClass({
render: function(){
return (
<h1>Today is {this.props.day}!</h1>
);
}
});

React.renderComponent(
<DayComponent day="Sunday" />,
document.getElementById('example')
);

Während props unveränderlich (immutable) angelegt und für den Read-only-Zugriff gedacht sind, ermöglicht state Interaktionen. Er ist innerhalb der Komponente zu finden und lässt sich beispielsweise beim Klick auf einen Button oder bei der Rückgabe eines REST-Services mit this.setState() verändern. Verwendet die render-Methode ebenfalls den Status der Komponente, wird sie bei einer Änderung automatisch neu gerendert.

Beim Erzeugen einer Komponente holt sie sich ihren Zustand optional mit der getInitialState-Methode:

var DayComponent = React.createClass({
getInitialState: function(){
return {
day: "Tuesday"
}
},
render: function(){
return (
<h1>{this.state.day}</h1>
)
}
});

Lädt die Anwendung Daten via GET Request vom Server, werden sie in die Komponenten gespiegelt. Beispielsweise lässt sich mit jQuery ein asynchroner Request an den Server stellen und bei erfolgreicher Rückgabe direkt auf den state setzen:

var DayComponent = React.createClass({
...
getInitialState: function() {
return {data: []};
}
componentDidMount: function() {
$.get({
url: this.props.url,
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this);
});
}
...
});

Nach dem Rendern ruft React automatisch die componentDidMount-Methode auf. Aktualisiert die Anwendung den Status mit this.setState(), ersetzen die neuen Daten vom Server den anfänglichen data-Array und bringen die Komponente so auf den neusten Stand. Neben der componentDidMount gibt es noch weitere Methoden, die im nächsten Abschnitt genauer erklärt werden.