Dieser Artikel richtet sich nicht an erfahrene React-Profis, sondern an diejenigen von uns, die beruflich Webseiten erstellen und neugierig sind, wie React uns helfen kann, über die Aktualisierung von Benutzeroberflächen nachzudenken. Ich war schon seit einiger Zeit von React fasziniert, und da es nun einen gewissen Stellenwert in der Community sowie gute Bewertungen erlangt hat, schien der Zeitpunkt zum Lernen gerechtfertigt. Es gibt ständig so viele neue Technologien in der Frontend-Entwicklung, dass es manchmal schwer zu wissen ist, ob sich die Mühe, etwas Neues zu lernen, auszahlt. In diesem Artikel werde ich darlegen, was meiner Meinung nach die wertvollsten praktischen Erkenntnisse sind, damit Sie loslegen können.
Faire Warnung
Ich habe nur etwa eine Woche mit diesem Material gearbeitet. Das ist Absicht. Ich schreibe dies, während ich noch frisch mit der Technologie bin und darüber aus dieser Perspektive schreiben kann. In diesem Zustand kann ich mich viel besser an die Stolpersteine und Erkenntnisse erinnern, die mir auf dem Weg begegnet sind.
Ich habe den Kurs von Wes Bos, React for Beginners, sowie React.js Introduction For People Who Know Just Enough jQuery To Get By genutzt. Ich kann diese Ressourcen nicht genug empfehlen.
In zwei Tagen habe ich das gemacht
Siehe den Pen Baby’s First React Attempt von Sarah Drasner (@sdras) auf CodePen.
Es ist nicht perfekt, aber es geht weit über das hinaus, was ich in dieser Zeit allein hätte erreichen können.
Wenn Sie zu den Leuten gehören, die sich direkt hineinstürzen und alles lernen möchten, einschließlich des Builds und des erforderlichen Toolings, dann ist das großartig! Hier können Sie beginnen. Ich würde auch diesen ziemlich guten Frontend Masters Kurs empfehlen: Modern Web Apps.
Mythbusters: Ausgabe Praktikabilität in React
Bevor wir beginnen, möchte ich ein paar wichtige Mythen entkräften, die meiner Meinung nach für viele Leute hinderlich sind.
Myth #1: Sie müssen Inline-Styles verwenden, um React zu nutzen.
Nein! Überhaupt nicht. Sie können CSS wie gewohnt verwenden. Nachdem ich viel Zeit mit der Refaktorierung einer riesigen CSS-Codebasis verbracht habe, würde ich sagen, dass dies ziemlich wichtig ist. React, da es ziemlich neu ist, hat sich noch nicht dem Test von Design-Updates gestellt, wie es andere Technologien getan haben. Wenn ich Tausende von Zeilen mit Inline-Styles durchgehen müsste, nur um Dinge wie padding und line-height zu aktualisieren, wäre ich ein trauriger Entwickler.
Das gesagt, es gibt Zeiten, in denen Inline-Styles Sinn machen. Wenn Sie eine Komponente haben, die ihre Stile je nach Zustand ändert (z. B. eine Datenvisualisierung), wäre es sinnvoll, mit Inline-Styles zu arbeiten, damit Sie keine unpraktische Anzahl statischer Stile (an mehreren Stellen) pflegen müssen, um alle möglichen Zustände abzudecken.
Ich würde jedoch denken, dass dies zusätzlich zu einem Basis-CSS liegt, das die Anwendung verwendet, und eher eine Ausnahme als eine Regel darstellt. Die Web ist ein großer Ort, daher gibt es keine Absolutheit.
Myth #2: Sie müssen JavaScript-Syntax für Elementattribute verwenden, was überhaupt nicht wie HTML ist.
Eines der Dinge, die ich am Lehrstil von Wes Bos wirklich liebe, ist, dass er den Zuschauer zum vertrauteren Ansatz und zur vertrauteren Implementierung führt. Ich neige generell dazu, auf der Seite des einfachen, weniger verschleierten Codes zu bleiben, obwohl ich verstehe, dass andere höhere Abstraktionsebenen bevorzugen.
Er schlägt vor, unser Markup mit JSX zu schreiben, was unserem Freund, dem traditionellen HTML, ähnlicher ist, daher fand ich es viel klarer. Anstatt also dies
return React.createElement("p", {className: "foo"}, "Hello, world!");
Würden wir das schreiben
return (<p className="foo">Hello, world!</p>);
Beides funktioniert. Aber wenn unsere Markup immer komplexer wird, habe ich festgestellt, dass die Vertrautheit von HTML in Form von JSX meinem Verständnis diente. Bitte bedenken Sie jedoch, dass es auch mit JSX geringfügige Unterschiede gibt.
Myth #3: Um React auszuprobieren, müssen Sie alle Build-Tools verstehen.
Es stimmt zwar, dass Sie zum Verwenden von React Build-Tools verwenden müssen, weshalb Tutorials normalerweise damit beginnen. Ich würde jedoch empfehlen, dass Sie sich als absoluter Anfänger auf CodePen austoben. Es ist eine gute Möglichkeit, schnell zu iterieren und zu lernen, bevor Sie viel Zeit in eine brandneue Technologie investieren.
React in typischen Anwendungen verwenden
In typischen Anwendungen, die React 1.14+ verwenden, würden wir damit beginnen, React und ReactDOM anzufordern
var React = require('react');
var ReactDOM = require('react-dom');
Und dann ReactDOM.render aufrufen
ReactDOM.render(routes, document.querySelector('#main'));
React in CodePen verwenden
In unserem Fall wählen wir einfach React aus dem Dropdown-Menü im JS-Panel (klicken Sie auf das Zahnradsymbol oben im Panel) und verwenden dann Babel als Compiler.

Wir müssen React oder React DOM nicht requiren, da wir nichts geroutet haben und die App-Komponente direkt verwenden. Unser Code wird einfach geändert zu
React.render(<App/>, document.querySelector("#main"));
<div id="main"></div>
Außerdem benötigen Sie zum Starten die React Devtools-Erweiterung für Chrome oder die React Devtools-Erweiterung für Firefox, die hervorragend zum Debuggen unseres virtuellen DOMs geeignet ist.
Wenn Sie CodePen verwenden, können Sie die Debug View verwenden, und sie findet React richtig

Einsatzbereit
Die grundlegenden Bausteine, die Sie kennen müssen, um etwas zu erstellen, sind wie folgt:
// App
var App = React.createClass({
render: function() {
return (
<div className="foo">Hello, world!</div>
)
}
});
ReactDOM.render(<App/>, document.querySelector("#main"));
Siehe den Pen Hello World React von Sarah Drasner (@sdras) auf CodePen.
Lassen Sie uns das aufschlüsseln. In der letzten Zeile finden wir die main div-ID, und darauf rendern wir die <App />-Komponente, die unsere gesamte React-Anwendung lädt. Sie können Ihren React-Tab in Devtools verwenden, um nun das erstellte DOM-Element zu sehen.
Wir haben <App /> als erste Komponente angehängt. Das Erste, was hier zu beachten ist, ist, dass dieses Tag großgeschrieben ist – obwohl dies nicht zwingend erforderlich ist, ist es eine bewährte Methode bei React-Komponenten. Das Zweite ist, dass es selbstschließend ist. Tags in React müssen geschlossen werden, entweder durch ein zusätzliches schließendes Tag (z. B. </div>) oder ein selbstschließendes Tag (z. B. <hr> würde zu <hr /> werden). Das ist einfach die Funktionsweise von JSX, andernfalls wird ein Fehler ausgelöst.
Beachten Sie die Struktur zur Erstellung der App-Komponente oben. Sie werden sich sehr an diese Syntax gewöhnen, da alles, was wir heute bauen werden, auf diesem Schlüsselbaustein basiert.
Das Letzte, was zu beachten ist, ist, dass wir anstelle von class className auf dem Element verwenden. Dies ist ein Stolperstein, wenn Sie daran gewöhnt sind, HTML-Markup für eine Webseite zu schreiben. Glücklicherweise ist es leicht zu lösen. Weitere Informationen zu JSX und seiner Syntax finden Sie in diesen Dokumenten, die wirklich gute Ressourcen sind.
// App
var App = React.createClass({
render: function() {
return (
<Header />
)
}
});
// Header
var Header = React.createClass({
render: function() {
return (
<div className="foo">Hello, world!</div>
)
}
});
ReactDOM.render(<App/>, document.querySelector("#main"));
Siehe den Pen Hello World React von Sarah Drasner (@sdras) auf CodePen.
Im nächsten Schritt erweitern wir die App mit einer Komponente. Header kann beliebig benannt werden, zur Klarheit haben wir ihn nach seiner Rolle im Dokument benannt. Sie können sehen, dass wir, wenn wir auch ein Navigationselement hinzufügen wollten, dies ziemlich einfach tun könnten. Hier ist die gleiche Seite mit einer Standard-Bootstrap-Reihe von Schaltflächen für eine <Nav />-Komponente und der semantischeren h1 für unser „Hello, World!“ anstelle eines div
// App
var App = React.createClass({
render: function() {
return (
<div>
<Nav />
<Header />
</div>
)
}
});
// Nav
var Nav = React.createClass({
render: function() {
return (
<ul className="nav nav-pills">
<li role="presentation" className="active">Home</li>
<li role="presentation">Profile</li>
<li role="presentation">Messages</li>
</ul>
)
}
});
// Header
var Header = React.createClass({
render: function() {
return (
<h1 className="foo">Hello, world!</h1>
)
}
});
ReactDOM.render(<App/>, document.querySelector("#main"));
Siehe den Pen Hello World React von Sarah Drasner (@sdras) auf CodePen.
Ziemlich einfach, oder? Es ist wie die Bausteine jeder Webseite. Wir erstellen die Navigation und den Header und wenden diese Komponenten auf die App-Komponente an, die im Body gerendert wird. Der einzige wirkliche Stolperstein des letzten Beispiels wäre das seltsame zusätzliche Div, das Sie um <Header /> und <Nav /> sehen. Das liegt daran, dass wir immer ein einziges Element zurückgeben müssen. Wir können keine zwei Geschwisterelemente haben, also packen wir sie in ein einziges Div.
Nachdem Sie nun die Bausteine verstehen, können Sie wahrscheinlich ziemlich einfach eine Seite mit React und React-Komponenten zusammenstellen. Ich würde vorschlagen, ein Seitenlayout zu refaktorieren, das Sie bereits erstellt haben, nur um zu lernen. Werfen Sie das Stylesheet hinein und fügen Sie die restlichen Teile Stück für Stück zusammen, bis Sie das Gerüst rekonstruiert haben. Es ist eine großartige Übung.
Es gibt eine Möglichkeit, diesen Prozess zu automatisieren, aber ich würde nicht empfehlen, ein solches Tool zu verwenden, bis Sie die Schritte des Erstellens von Dingen selbst bereits durchlaufen haben. Auf diese Weise wissen Sie, was vor sich geht, wenn Sie später auf Probleme stoßen.
Die üblichen Verdächtigen: Variablen & Event-Handling
Lassen Sie uns etwas einfaches Event-Handling machen und zuerst ein paar einfache Variablen einfügen, nur um zu sehen, wie das funktioniert.
Betrachten Sie die erste Demo noch einmal (wir werden diese im gesamten Artikel verwenden)
Siehe den Pen Baby’s First React Attempt von Sarah Drasner (@sdras) auf CodePen.
Die Blog-Post-Komponente hat ein ziemlich einfaches Markup, also fangen wir damit an
// Blog Post
var Post = React.createClass({
render : function() {
return (
<div className="blog-post">
<h3 className="ptitle">{this.props.ptitle}<small>{this.props.date}</small></h3>
<img className="thumbnail" src={this.props.pimg} />
<p>{this.props.postbody}</p>
<div className="callout callout-post">
<ul className="menu simple">
<li>Author: {this.props.author}</li>
<li>Comments: {this.props.comments}</li>
<li>Tags: {h.getTaggedName()}</li>
</ul>
</div>
</div>
)
}
});
Fügen wir eine beliebige Variable und einen Event-Handler hinzu, um zu sehen, wie das funktioniert. Das Erste, woran man denken muss, ist, dass geschweifte Klammern React mitteilen, dass wir bereit sind, JavaScript zu verwenden, wenn wir JSX verwenden. Daher wird unsere Variable so aussehen: {var}.
Wir fügen die Variablendeklaration innerhalb des render-Funktionsaufrufs ein, aber bevor wir das Markup zurückgeben. Wir können dann darauf zugreifen, indem wir die Variable aufrufen, in diesem Fall {com}. Das Klickereignis ist ein Inline-onClick-Handler, der wahrscheinlich gegen die Best Practices verstößt, an die Sie gewöhnt sind. Dies ist ein Name, den wir gewählt haben, während render eine Framework-Methode ist. Wir rufen {this.tryClick} auf und schreiben eine Methode namens tryClick (ein beliebiger Name) innerhalb derselben Komponente, wie folgt:
// Blog Post
var Post = React.createClass({
tryClick : function() {
alert('just trying out click events lalala');
},
render : function() {
var com = "Comments";
return (
<div className="blog-post">
<h3 className="ptitle">{this.props.ptitle}<small>{this.props.date}</small></h3>
<img className="thumbnail" src={this.props.pimg} />
<p>{this.props.postbody}</p>
<div className="callout callout-post">
<ul className="menu simple">
<li>Author: {this.props.author}</li>
<li>{com}: {this.props.comments}</li>
<li>Tags: {h.getTaggedName()}</li>
</ul>
</div>
</div>
)
}
});
Die Syntax für Ereignisse in React beginnt mit „on“ und ist camel-cased. Zum Beispiel
- click = onClick
- mouseEnter = onMouseEnter
- keyPress = onKeyPress
Sie finden eine vollständige Liste aller unterstützten Ereignisse.
Kombination von React und anderen Bibliotheken (hier: Greensock)
Ich liebe GSAP für Animationen. Sie können andere Bibliotheken innerhalb von React verwenden, also kombinieren wir GSAP und React und sehen, wie das funktioniert.
Wir wollen auf andere Bibliotheken zur richtigen Zeit zugreifen, also müssen wir sicherstellen, dass sie unmittelbar nach der ersten Render-Methode aufgerufen werden. Die Methode, die wir dafür verwenden, heißt componentDidMount. Wir werden weiter unten etwas mehr über andere Lifecycle-Methoden erklären, aber was Sie im Moment wissen müssen, ist, dass diese Methode unmittelbar nach dem Einfügen der Komponente in das Dokument aufgerufen wird.
Wenn Sie jQuery gewohnt sind, sind Sie es gewohnt, Elemente direkt aus dem DOM zu greifen. In diesem Fall verwenden wir, obwohl wir DOM-Elemente tweaken, Reacts getDOMNode() anstelle des direkten Zugriffs. Sie werden auch sehen, dass wir die Funktion zum Tween tatsächlich in der App-Komponente aufrufen und sie einfach an unsere Boxen weitergeben. (Möglicherweise müssen Sie auf "wiederholen" klicken, um die Animation zu sehen.)
Siehe den Pen 794b375a8725b039483c83fb63a4bd5a von Sarah Drasner (@sdras) auf CodePen.
// App
var App = React.createClass({
componentDidMount: function() {
var sq1 = this.refs.first.getDOMNode();
var sq2 = this.refs.second.getDOMNode();
var sq3 = this.refs.third.getDOMNode();
var sq4 = this.refs.fourth.getDOMNode();
var sq5 = this.refs.fifth.getDOMNode();
var allSq = [sq1, sq2, sq3, sq4, sq5];
TweenLite.set(allSq, {css:{transformPerspective:400, perspective:400, transformStyle:"preserve-3d"}});
TweenMax.to(sq1, 2.5, {css:{rotationX:230, z:-600}, ease:Power2.easeOut}, "+=0.2");
TweenMax.to(sq2, 2.5, {css:{rotationY:230, z:-150}, ease:Power4.easeOut}, "+=0.2");
TweenMax.to(sq3, 2.5, {css:{rotationX:500, z:150}, ease:Power2.easeInOut}, "+=0.2");
TweenMax.to(sq4, 2.5, {css:{rotationY:500, z:-150}, ease:Power4.easeOut}, "+=0.2");
TweenMax.to(sq5, 2.5, {css:{rotationX:1000, z:100}, ease:Power2.easeOut}, "+=0.2");
},
render: function() {
return (
<div className="scene">
<Box ref="first"></Box>
<Box ref="second"></Box>
<Box ref="third"></Box>
<Box ref="fourth"></Box>
<Box ref="fifth"></Box>
</div>
)
}
});
// Box
var Box = React.createClass({
render: function() {
return (
<div className="squares"></div>
)
}
});
ReactDOM.render(<App/>, document.querySelector("#main"));
Sie sind es vielleicht gewohnt, über jQuery oder Vanilla JavaScript auf das DOM zuzugreifen. Wir können dies immer noch tun, aber hier greifen wir über getDOMNode() und refs auf DOM-Teile zu, in dieser Zeile: var sq1 = this.refs.squares1.getDOMNode();. Sie können hier etwas mehr darüber lesen: React docs.
Es gibt spezifischere React-Methoden, um Bewegung in Ihre Projekte einzubinden – eine wirklich großartige ist Cheng Lous React-Motion und eine weitere gute Erwähnung ist React-GSAP-Enhancer.
Erstellen einer globalen Hilfsfunktion
Sie können sogar Hilfsfunktionen schreiben, auf die mehrere Komponenten leicht zugreifen können. Wir würden diese mit der gleichen Punktnotation verwenden, die wir mit this.functionName verwendet haben. Wir speichern die Hilfsfunktion (in diesem CodePen-Demo tun wir dies am Anfang der Datei, in realen Anwendungen werden sie jedoch in einer separaten Datei gespeichert) und deklarieren jede Funktion als Objekt, genauso wie Sie es innerhalb der Komponentenstruktur tun.
So etwas wie das korrekt formatierte Datum in der ersten Demo mit den Blogbeiträgen wäre
var h = {
getTime: function() {
var month = ["jan", "feb", "march"]; // …. and so on
var d = new Date();
var mon = month[d.getMonth()];
var day = d.getDate();
var year = d.getFullYear();
var dateAll = mon + " " + day + ", " + year;
return dateAll;
}
};
Und wird so verwendet: {h.getTime()}
Das Gute: State Management
Ok! Nachdem wir die Grundlagen geklärt haben, kommen wir zu einigen der coolen Sachen.
React ist sicherlich gut darin, Apps mit leicht verständlichen, kleinen Komponenten zu erstellen, aber es ist besonders gut darin, den Zustand (State) für diese Komponenten zu verwalten. Tauchen wir ein wenig tiefer ein.
Für diesen Teil werden wir zwei wichtige Aspekte des Zugriffs auf und der Arbeit mit sich ändernden Dingen besprechen.
- Das erste ist state. Die Komponente selbst besitzt ihn, was bedeutet, dass er auf die Komponente beschränkt ist und wir ihn so referenzieren:
{this.state.foo}. Wir können den state durch Aufruf vonthis.setState()aktualisieren. - Das zweite bezieht sich darauf, wie wir schreibgeschützte Daten vom Elternteil an die Komponente weitergeben (denken Sie daran, dass
appder Elternteil vonheaderim ersten Beispiel ist). Wir bezeichnen dies als props, also als Eigenschaft, und verwenden sie direkt in den Komponenten mit{this.props.foo}. Diese Daten können von ihren Kindern nicht geändert werden.
Jedes Mal, wenn wir eines dieser beiden Dinge ändern und unsere Komponente davon abhängt, wird React die Teile Ihrer Komponente, die es benötigt, neu rendern.
Die Schönheit des virtuellen DOM ist, dass React nur herausfindet, welche DOM-Knoten aktualisiert werden müssen.
Ich habe viel über State gelesen, aber ich glaube, Wes hat es am klarsten formuliert, also werde ich ihn paraphrasieren: Wenn Sie jQuery gewohnt sind, speichern Sie alle Ihre Daten im DOM. React vermeidet dies gänzlich, indem es die Daten in einem Objekt (State) speichert und dann Dinge basierend auf dem Objekt rendert. Es ist wie ein großes Master-Objekt, auf dem alles basiert.
Props ausprobieren
Probieren wir zuerst this.props aus. Wir fügen {this.props.title} zur Header-Komponente hinzu und können dann über die App darauf zugreifen. Wir fügen einen String hinzu, um den Titel zu erstellen
// App
var App = React.createClass({
render: function() {
return (
<Header greeting="Hello, world!" />
)
}
});
// Header
var Header = React.createClass({
render: function() {
return (
<div className="foo">
<h1>{this.props.greeting}</h1>
</div>
)
}
});
ReactDOM.render(<App/>, document.querySelector("#main"));
Wir können auch einen Standardwert für Props in der passend benannten getDefaultProps-Lifecycle-Methode hinzufügen. Das ist großartig, weil man manchmal nicht für jede Komponente Props angeben muss. Ein Beispiel dafür wäre ein Standard-Profil-Avatar, wenn der Benutzer noch keinen festgelegt hat, wie das Ei bei Twitter, oder das Setzen einer Liste als leeres Array, das später gefüllt wird.
var ProfilePic = React.createClass({
getDefaultProps: function() {
return {
value: 'twitter-egg.jpg'
};
...
});
Sachen machen
Lassen Sie uns nun darauf aufbauen, um ein wenig mit State zu arbeiten. Wenn wir this.state schließlich ändern wollen, müssen wir ihn vorbereiten. Dazu verwenden wir getInitialState, was uns erlaubt, zu definieren, was der State von Anfang an ist. Ohne dies können wir keinen State hinzufügen.
Ändern wir einfach den Hintergrund basierend auf der Benutzerauswahl.
Siehe den Pen 928579628fd2ecb0f98aff9c08774e93 von Sarah Drasner (@sdras) auf CodePen.
// App
var App = React.createClass({
/*setting state*/
getInitialState: function() {
return {
bgColor: "teal"
};
},
/*changes state*/
handleColorChange: function (color) {
// when we set state directly, react doesn't know
// about it. that's why we use setState
this.setState({ bgColor: color });
},
/*for the lifecycle methods*/
updateBackgroundColor: function () {
var body = document.querySelector('body')
body.style.background = this.state.bgColor
},
/*lifecycle methods*/
componentDidMount: function () {
this.updateBackgroundColor()
},
componentDidUpdate: function () {
this.updateBackgroundColor()
},
render: function() {
return (
/* by calling the title here on the component, we can access this.props on header */
<div className="foo">
<h1>Hello, World!</h1>
<label>What color?
<ColorPicker value={this.state.bgColor} onColorChange={this.handleColorChange}/>
</label>
</div>
)
}
});
// ColorPicker component
var ColorPicker = React.createClass({
propTypes: {
value: React.PropTypes.string.isRequired,
onColorChange: React.PropTypes.func
},
handleChange: function(e) {
e.preventDefault();
var color = e.target.value
// If whoever rendered us (the ColorPicker) is interested
// when the color changes, let them know
if (this.props.onColorChange)
this.props.onColorChange(color);
},
render: function() {
return (
<select value={this.props.value} onChange={this.handleChange}>
<option value="orangered">orangered</option>
<option value="teal">teal</option>
<option value="orange">orange</option>
<option value="indigo">indigo</option>
<option value="red">red</option>
</select>
)
}
});
ReactDOM.render(<App/>, document.querySelector('#main'));
Ein wichtiger Teil davon ist zu bedenken, dass wir die handleChange-Funktion benötigen.
Im normalen DOM-Leben würden native Auswahlen nicht erfordern, dass Sie so etwas tun, da sie sich automatisch an die Auswahl des Benutzers anpassen würden. In React wird der gesamte State von der Komponente verwaltet. Wenn Sie also möchten, dass ein Eingabefeld oder eine Auswahl auf Änderungen reagiert, müssen Sie dies selbst schreiben. Das bedeutet, dass die Komponente für den State verantwortlich ist, nicht der Benutzer.
Das mag nach viel Arbeit für wenig Ertrag aussehen, aber wir haben diese Beispiele bewusst schlank gehalten. Die coolen Teile von React kommen wirklich zum Tragen, wenn Sie mit viel Komplexität umgehen. So sehr ich jQuery liebe (und ich liebe jQuery immer noch, es ist keine boolesche Variable), Sie müssen ziemlich häufig Überprüfungen durchführen, wenn sich etwas ändert. React löst dies, indem es diese Notwendigkeit aufgrund der Einfachheit des Datenflusses beseitigt, was es auch in hochkomplexen Anwendungen leichter verständlich macht.
State-Konzepte
Nachdem wir nun die absoluten Grundlagen beherrschen, werfen wir einen schnellen Blick darauf, warum wir das tun, was wir tun, sowie auf einige Best Practices.
React funktioniert am besten, wenn wir States aktualisieren und untergeordnete Komponenten neu rendern. Grundsätzlich möchten wir, dass diese Komponenten größtenteils zustandslos sind und Daten von übergeordneten Komponenten erhalten. Die Komponenten an der Spitze unserer Hierarchie, wie unsere App, funktionieren am besten, wenn sie größtenteils zustandsbehaftet sind. Auf diese Weise verwalten sie den Großteil der Interaktionslogik und übergeben den State mithilfe von Props. Dennoch wird es Zeiten geben, in denen jede Komponente ihren eigenen State hat. Es ist jedoch wichtig zu bedenken, dass Geschwister nicht direkt miteinander sprechen sollten, sondern mit ihrer Elternkomponente.

Daher möchten wir den State so weit wie möglich in der Komponente behalten. Sie müssen sich nie wirklich darum kümmern, *wann* etwas gerendert wird. Alles, worum Sie sich kümmern müssen, ist, wann sich der State ändert, und React kümmert sich um das Rendering für Sie.
Diese Art von Best Practice führt direkt dazu, warum ich Ihnen auch davon abrate, Props in getInitialState zu verwenden, und hier gibt es weitere Informationen darüber, warum dies als Antipattern gilt.
Wir sollten State nicht überstrapazieren. Das Rendern der Komponenten ist ziemlich schnell, aber die Leistung kann sinken, wenn Sie versuchen, zu viel State zu verwalten. Es gibt einige Möglichkeiten, dies zu umgehen, sobald es tatsächlich ein Problem ist, aber am besten ist es, gar nicht erst in diese Lage zu geraten.
Der Rest dieses Artikels befasst sich damit, wie man diese States am besten verwaltet und die unveränderlichen Bedenken in der oberen Hierarchie belässt, während man sich immer noch auf unsere zustandslosen Komponenten weiter unten bezieht.
Referenzen
Wir können auch auf Informationen über das Element mit etwas namens ref zugreifen. Wir verwenden Refs, indem wir sie an jede Komponente anhängen. Sie wird dann während der render()-Methode zurückgegeben, und wir können uns dann außerhalb der render()-Methode darauf beziehen. Das ist unglaublich nützlich.
Betrachten wir noch einmal den ersten Pen. Denken wir einen Moment darüber nach, wie wir diese neuen Blogbeiträge erstellen, und nutzen wir dabei Refs.
In jedem Formulareingabefeld haben wir eine Referenz, wie z.B.
<input type="text" ref="name" placeholder="Full Name required" required />
Am Formularelement selbst rufen wir
onSubmit={this.createPost}
auf, was sich auf die Funktion createPost oberhalb der Render-Funktion bezieht und Refs verwendet, um Informationen aus dieser Einreichung zu speichern.
var post = {
name : this.refs.name.value,
...
}
und dann haben wir eine Möglichkeit, darauf im App-Status mit this.props zu verweisen.
this.props.addPost(post);

Das ist ziemlich praktisch, denn jetzt haben wir eine Variable `post`, die Objekte mit Informationen über ihren Namen (hier gezeigt), Datum, Details usw. speichert. Wir haben das alles noch nicht im App-Status gespeichert, sondern nur einen Weg dafür geschaffen, dass die App es verwenden kann. Das behandeln wir als Nächstes, zusammen mit keys.
Ich habe dieses Beispiel verwendet, um über Refs im Allgemeinen zu sprechen, aber in realen Anwendungen sollten Sie vielleicht etwas wie form-serialize in Betracht ziehen, um Formularfelder für die Übermittlung über AJAX zu serialisieren.
Keys und Verwendung von Refs
In unserem letzten Abschnitt haben wir eine Möglichkeit geschaffen, die gesammelten Daten aus dem Formular zu speichern, ohne sie weiterzugeben. Das liegt daran, dass wir in React diesen Zustand auf der obersten Ebene unserer Hierarchie verwalten wollen. Um diesen Zustand zu speichern, initialisieren wir unseren anfänglichen Zustand mit einem leeren Objekt. Dort werden wir letztendlich unsere Post-Daten speichern.
getInitialState : function() {
return {
posts: {}
}
},
Dann haben wir unsere `addPost`-Funktion. Beachten Sie, dass wir diese hier statt im Formular verwalten, obwohl wir sie vom Formular aus aufgerufen haben. Wir geben dem Zustand einen Zeitstempel, um die Beiträge eindeutig zu halten, und setzen auch den Zustand für die Beiträge.
addPost: function(post) {
var timestamp = (new Date()).getTime();
// update the state object
this.state.posts['post-' + timestamp] = post;
// set the state
this.setState({ posts : this.state.posts });
},
Jedes Kind in einem Array sollte einen eindeutigen key.prop haben. Dies ist wichtig, da React so viel wie möglich vom vorhandenen DOM wiederverwenden wird. React verwendet keys, um zu verfolgen, welche Elemente im DOM es aktualisieren soll. Das erspart uns das Neuzeichnen aller DOM-Elemente, wenn wir neu rendern. Das hilft der Leistung unserer App.
Schauen wir uns jetzt noch einmal die App an und sehen wir, was wir mit unseren neu gespeicherten Daten aus dem Formular machen.
// App
var App = React.createClass({
getInitialState : function() {
return {
posts : {}
}
},
addPost : function(post) {
var timestamp = (new Date()).getTime();
// update the state object
this.state.posts['post-' + timestamp] = post;
// set the state
this.setState({ posts : this.state.posts });
},
renderPost : function(key){
return <NewPost key={key} index={key} details={this.state.posts[key]} />
},
render : function() {
...
return (
<div>
<Banner />
...
<div className="list-of-posts">
{Object.keys(this.state.posts).map(this.renderPost)}
</div>
<Submissions addPost={this.addPost}/>
</div>
</div>
)
}
});
Sie sehen, dass wir beim Rendern der App `Object.keys` verwenden, um ein neues Array zu erstellen. Dann verwenden wir .map() mit der zuvor erstellten Funktion `renderPost`. Für diejenigen, die mit .map() nicht vertraut sind: Es ist nützlich, um ein Array aus einem vorhandenen zu erstellen, man kann es sich wie eine Schleife vorstellen.
<div className="list-of-posts">
{Object.keys(this.state.posts).map(this.renderPost)}
</div>
Lassen Sie uns nun die `renderPost`-Funktion erstellen, die wir gerade aufgerufen haben. Wir übergeben den Schlüssel als Parameter und weisen ihn als Schlüssel zu, den Index, und erstellen ein Objekt, das wir `details` nennen, um Informationen über den Zustand der Beiträge zu speichern.
renderPost: function(key) {
return <NewPost key={key} index={key} details={this.state.posts[key]} />
},
Es mag seltsam erscheinen, dass wir einen key und einen index übergeben, aber innerhalb einer Komponente können wir die Schlüssel-prop nicht aufrufen, daher übergeben wir eine andere namens index. Diese `renderPost`-Funktion erstellt einfach eine <NewPost />-Komponente für jedes Element in unserem Array, mit übergebenen Details, auf die wir zugreifen können. Das ist ziemlich genial, denn das bedeutet, dass, wenn sich etwas in unserem Zustand ändert, es sich nach unten ausbreitet und wir es an einer Stelle verwalten können.
Hier ist die <NewPost />-Komponente, in der wir die von der App übergebenen Details verwenden, um alle Informationen zu rendern. Sie sehen, dass die zuvor erstellte Hilfsfunktion für das korrekt formatierte Datum hier als {h.getTime()} verwendet wird.
/*
NewPost
<NewPost />
*/
var NewPost = React.createClass({
render : function() {
var details = this.props.details;
return (
<div className="blog-post">
<h3 className="ptitle">{details.title}<small>{h.getTime()}</small></h3>
<img className="thumbnail" src={details.image} alt={details.name}/>
<p>{details.desc}</p>
<div className="callout callout-post">
<ul className="menu simple">
<li>Author: {details.name}</li>
<li>Comments: 0</li>
<li>Tags: {h.getFunName()}</li>
</ul>
</div>
</div>
)
}
});

Siehe den Pen Baby’s First React Attempt von Sarah Drasner (@sdras) auf CodePen.
Alles zusammen jetzt
Jetzt, wo wir Keys verstehen, schauen wir uns die große Zusammenfassung an. Wir haben getInitialState, componentDidMount und render besprochen, aber es gibt noch eine weitere Montagemethode für React. Sie heißt componentWillMount. Sie ähnelt componentDidMount, wird aber sofort ausgeführt, *bevor* die Komponente zum ersten Mal gerendert wird.

Dieses Diagramm enthält nicht alles, was in React verfügbar ist, sondern nur einen Einblick in das, was wir bisher behandelt haben und genug, um Ihnen den Einstieg zu ermöglichen.
Fazit
Es gibt viel mehr zu lernen als in diesem Artikel über React, dies ist nur der Anfang. Hoffentlich gibt diese Anfängerreise anderen einen kleinen Einblick, wie man loslegt. Dieser Beitrag war 20 Seiten lang und wir sind noch nicht einmal auf eine Menge anderer wichtiger und verwandter Themen eingegangen, darunter unter anderem ES6, Browserify, Gulp, Webpack oder eine Vielzahl alternativer Implementierungen.
Für weiteres Lernen empfehle ich nochmals *dringend*, sich in Wes Bos' Kurs zu vertiefen. Er bietet einen Rabatt von 10 % für CSS-Tricks-Leser mit dem Code CSSTRICKS, sowie Videos auf Frontend Masters. Michael Jackson hat einen wunderbaren Schulungskurs, für den Sie sich anmelden können (er kommt im März nach Trulia in San Francisco! Bleiben Sie dran für Anmeldungen). Es gibt auch ein großartiges Buch von Artemij Fedosejev namens React Essentials und diese Liste, die es wert ist, von Artem Sapegin als Lesezeichen markiert zu werden. Es sollte nicht unterschätzt werden, dass die React Docs ziemlich gute Ressourcen sind. Viel Spaß beim Lernen!
Vielen Dank an Michael Jackson, Wes Bos und Val Head für das Korrekturlesen dieses Artikels.
Danke, Sarah, coole Einführung. Ich bin nur ein bisschen verwirrt (hatte noch keine Gelegenheit, das ganze Tutorial im Detail durchzugehen) – sollte Ihre Anwendung auch Kommentare hinzufügen oder ist die einzige Funktionalität das Formular zum Hinzufügen eines Beitrags zum Blog?
Hallo Lubos,
Die tatsächliche Anwendung sollte jede Menge Dinge tun, die sie in dieser Demo nicht tut – es gibt keine Verbindung zum Backend, die Tags sind nicht echt, die Kommentare sind nicht echt, wir könnten Einzelansichten für Beiträge erstellen. Ich habe dieses Beispiel absichtlich sehr schlank gehalten, da es darum geht, die allerersten Schritte beim Aufbau zu zeigen. Ich wollte es so einfach wie möglich halten, um den Leuten den Einstieg und das Verständnis der Kernideen zu ermöglichen. Danke!
Sicher, das ist völlig in Ordnung, ich war mir nur nicht sicher, ob es etwas tun sollte oder ob etwas kaputt war. Vielleicht könnte eine kurze Notiz neben der Demo das verdeutlichen. Trotzdem ein tolles Tutorial.
Angenehm zu lesen. Vielen Dank.
Ich habe ein wenig über das Erlernen von React geschrieben, was für Leser nützlich sein könnte, sobald sie von Webseiten zu Apps wechseln.
http://developer.telerik.com/featured/5-steps-for-learning-react-application-development/
Danke Cody! Tolle Ressource, ich bin sicher, dass die Leute sie hier nützlich finden werden.
Danke für die Einführung in React. Ich habe Bibliotheken/Frameworks wie dieses eine Zeit lang evaluiert und darauf gewartet zu sehen, welche sich durchsetzen.
Haben Sie jemals Angular ausprobiert, bevor Sie sich für React entschieden haben? Wenn ja, warum haben Sie React gewählt?
Der Grund, warum ich frage, ist, dass ich ein früher Anwender von Prototype.js war und mit dieser Wahl auf die Nase gefallen bin. Ich räume immer noch einige Probleme auf, die von ihm in Projekten hinterlassen wurden...
Eine Nebenbemerkung: Keiner der Codepens funktionierte in Firefox (v 44 unter Linux Mint), was ich hoffe, ein Programmierfehler ist und nicht die Schuld von React. (Sie funktionieren aber in Chrome einwandfrei...)
Hallo Vanderson,
Ich habe gerade alle Demos in Firefox auf einem Mac erneut überprüft, und sie funktionieren alle. Ich muss mir Linux besorgen, um einige Tests durchzuführen, Entschuldigung dafür.
Ich habe Angular ausprobiert, ja – Vergleiche zwischen Angular und React sind ein wenig wie Äpfel und Birnen – Angular ist ein MVC, während React nur die View in MVC ist.
Ich empfehle Ihnen dringend, mit React zu experimentieren, bevor Sie sich auf Produktionscode festlegen, genau aus den von Ihnen genannten Gründen. Es ist ein Werkzeug wie jedes andere, und wie jedes andere hat es großartige Teile und Dinge, die ein wenig umständlicher sind (das ist meine persönliche Meinung). Es erfordert einige echte Umstellung, nicht Dinge aus dem DOM zu speichern und abzurufen, insbesondere das virtuelle DOM. Ich bin sicher, dass verschiedene Programmierer und verschiedene Programmieraufgaben dies unterschiedlich (und haben) umgesetzt haben.
Ich hoffe, das hilft!
Nun, die Beispiele funktionieren jetzt... Vorher blieben sie endlos im "loading....." in Codepen hängen. Wer weiß, was passiert ist.
Ich weiß nicht mehr, wie ich darauf gestoßen bin, aber ich schaue mir riot.js, vue.js und mithral an. Nach einigem Lesen fand ich riot.js' Erklärung, React + Polymer zu kombinieren. Und ich war sofort von Polymer begeistert, als ich zum ersten Mal einige Beispiele in einer Präsentation sah.
Der Grund, warum mir die Theorie hinter riot.js gefällt (natürlich recherchiere ich das heute erst), ist die Idee der Standards. Ich bin misstrauisch gegenüber Facebook, das nächstes Jahr ein Kernelement von React ändert, nur weil es ihnen am besten passt, oder wie Angular 1, sie erkennen, dass sie einen grundlegenden Fehler hatten, den sie beheben müssen.
Danke für die Ermutigung, die DOM-Interaktionen zu überdenken. Als ich React zum ersten Mal studierte, hat mich das ein wenig erschreckt. Aber ich schätze, das wird man verstehen, nachdem man es ausprobiert hat? (selbst Riot lobt React für dieses Kernkonzept)
(Entschuldigung für die Nachrichtenflut hier)
Mir ist gerade aufgefallen, dass riot.js One-Way-Data-Binding erzwingt, etwas, von dem das Facebook-Team zu spät erkannte, dass es Komplikationen in ihrer App verursacht hat.
Betrachten Sie, wie viel Arbeit das ist, um Flux zu implementieren: (d.h. einen benutzerdefinierten Dispatcher zu erstellen)
https://facebook.github.io/flux/docs/todo-list.html
Und wenn React einfach One-Way-Data-Binding erzwingen würde, wäre Flux nicht nötig. Zumindest das ist, was ich aus dieser Präsentation und einer schnellen Lektüre der Dokumentation mitnehme.
https://facebook.github.io/react/blog/2014/05/06/flux.html
Das scheint der gleiche grundlegende Fehler zu sein, den Angular 1 und Prototype.js usw. haben... Fehlt mir hier etwas? Ich spüre wegen Flux einfach einen "Code Smell" bei React.
Tolle Sachen :) Ich arbeite mich noch durch, aber... In der Demo unmittelbar vor dem Abschnitt "Die üblichen Verdächtigen: Variablen & Event Handling" enthalten die Elemente im geposteten Code keine
<a>-Elemente und erhalten nicht die Bootstrap-Formatierung, die sie in Ihrem Pen haben (der<a>s enthält). Keine große Sache, aber ich war etwas verwirrt, da ich dachte, ich würde perfekt folgen haha.Danke für diesen tollen Beitrag :D
Tolles Tutorial! Sie sind nicht in den üblichen Fall gestolpert, zu viele Konzepte in einem Tutorial einzuführen. Wenn Sie zum Beispiel React lernen, sollten Sie so viel "anderen Kram" wie möglich aus den Beispielen heraushalten, was ein minimales Set an ES2015 und so wenig Abstraktionen wie möglich bedeutet (Bibliotheken, die die Ausführlichkeit verringern). Leute sollten zuerst ausführlichen Code schreiben und wenn sie verstehen, was vor sich geht, dann anfangen, Bibliotheken zu verwenden, um diese Details zu verbergen.
Ich habe einen Blogbeitrag "Machen Sie das Lernen von React nicht schwieriger als es ist" geschrieben, der sehr beliebt war, da die Leute damit zu kämpfen scheinen. Ich hoffe, die Zielgruppe findet ihn "beruhigend". :)
Ausgezeichneter Artikel. Ich weiß nicht, warum ich mich nicht früher damit beschäftigt habe, aber jetzt haben Sie mich!
Großartig! Freut mich sehr, dass es nützlich war. Danke!
Hallo Sarah,
Guter Artikel!
Ich denke, bei "Mythos #2: Sie müssen JavaScript-Syntax für Elementattribute verwenden, was überhaupt nicht wie HTML ist." vermischen Sie ein paar Dinge: Attribute vs. Komponenten.
Sie haben Recht, dass Sie bei Komponenten die Möglichkeit haben, JSX anstelle der ausführlicheren JS-Syntax zu verwenden.
Wenn ich das richtig verstehe, müssen Element-**Attribute** (auch in JSX) jedoch immer in JS-Syntax (nämlich camelCase) vorliegen. Zum Beispiel müssen Sie
classNameund nichtclassverwenden (daclassein reserviertes Schlüsselwort in JS ist), oderdataMyAttrNameund nichtdata-my-attr-name.Ich hoffe, das hilft.
Danke fürs Aufpassen! Aber nein, ich bin überhaupt nicht verwirrt. Ich meinte Elementattribute, und wenn man sich die Beispiele ansieht, ähnelt JSX selbst mit camelCase der gängigen HTML-Syntax mehr, als Leute, die React-Docs auf den ersten Blick betrachten, vielleicht denken. Ich füge eine Einschränkung hinzu, dass sie unterschiedlich sind und erkläre das weiter unten im Artikel.
"Dieser Beitrag war 20 Seiten lang und wir sind noch nicht einmal..."
Gut gemacht, Sarah! Allerdings bin ich mir nicht ganz sicher, ob eine solch hohe Komplexität gut für die Web-Community insgesamt ist. Es gab eine Zeit, in der Sprachen (HTML, CSS) dem Leitprinzip des W3C, der Regel der geringsten Leistung, folgten.
Siehe auch Luke Plants exzellenter Artikel Wir brauchen weniger leistungsfähige Sprachen.
Für alle, die Node.JS verwenden, empfehle ich den Entwicklern dringend, sich eBay's opensource Marko.js ernsthaft anzusehen. Im Gegensatz zu React folgt Marko der *Regel der geringsten Leistung*. Marko Widgets ist die Antwort von eBay auf React, und die Lernkurve von Marko ist deutlich niedriger.
Marko ist eine HTML-basierte Template-Engine von eBay Open Source, die zum Rendern von Templates auf dem Server (Node.js) oder im Webbrowser verwendet werden kann. Es ist extrem schnell und leichtgewichtig (~3,75KB gzip), unterstützt aber auch Streaming und asynchrones Rendering. Entwickler können die HTML-Grammatik mit benutzerdefinierten Tags und benutzerdefinierten Attributen erweitern, um neue und wiederverwendbare Bausteine einzuführen. Der Marko-Compiler erzeugt Node.js-kompatible JavaScript-Module, die einfach zu lesen, zu verstehen und zu debuggen sind. eBay hat jedoch sehr wenig getan, um es zu bewerben (im Gegensatz zu Facebook, das React stark beworben hat und damit Komplexität beliebt gemacht hat).
Marko ist speziell darauf ausgelegt, der *Regel der geringsten Leistung* zu folgen, und Marko Widgets macht die Programmierung von SPA-ähnlichen Web-Apps zum Kinderspiel im Vergleich zu React. Um Ihnen eine Vorstellung zu geben, eBay bereitet die Veröffentlichung von Marko v3 vor, und die neue Syntax wird so aussehen:
Im Vergleich zu *React JSX*
eBay hat Benchmarks veröffentlicht, die zeigen, dass die serverseitige Leistung von Marko schneller und ausgereifter ist als die von React. Nicht nur das, eBay testet Marko.js seit einem Jahr im produktiven Einsatz und stellt derzeit alle seine Kerndienste auf Node.js und Marko um.
Für diejenigen, die Node.js verwenden, empfehle ich Marko gegenüber React und man kann hoffen, dass andere zukünftige Frontend-Sprachen die Bedeutung der *Regel der geringsten Leistung* anerkennen werden. Ich denke, React ist IMO auf dem falschen Weg. Aber hoffentlich wird sich das ändern.
Beste Grüße
Ich verfolge viele Ihrer Arbeiten, Sarah, und ich benutze React seit einigen Monaten, und ich denke, dies ist eine fantastische Einführung in React, besonders für diejenigen, die vielleicht etwas skeptisch und/oder verwirrt von einigen Konzepten sind.
Ich denke, ein guter Folgeartikel könnte Bibliotheken abdecken, die mit React kombiniert werden können, wie z.B. Redux, um den Anwendungsstatus zu verwalten. Ich persönlich liebe den Ansatz von Redux, bin aber neugierig, mir mehr anzusehen, ich habe gute Dinge über Cycle.js und RxJS gehört. Es wäre toll, Ihre Gedanken zu hören, falls Sie welche haben?
Danke!
Hallo! Das ist super, ich wollte nur, dass Sie darauf achten, wie Sie den Zustand in den Beispielen behandeln.
In der ersten Demo von "Usual Suspects" gibt es
this.state.posts[...] = post, das mutiert den React-Status und umgehtsetState. Sie können einfach so etwas tun:this.setState({posts: [...this.state.posts, post]})(das ist ES6-Destrukturierungssyntax, was bedeutet:...array=array[0], array[1], array[2], ..., array[end])Es funktioniert auch für Objekte, Sie können Dinge tun wie:
user: {...this.state.user, profilePicture: newProfilePicture }Trotzdem super. :)
Hallo, mir ist etwas aufgefallen, das nicht viel Sinn ergibt. Wenn Sie das Beispiel für Keys geben, speichern Sie Ihre Beiträge in einem Objekt und weisen den Schlüssel dem Objekt zu. Dann durchlaufen Sie das Objekt, rufen den Schlüssel ab und übergeben das gesamte Objekt und greifen über den Schlüssel erneut auf die Eigenschaft zu.
Original
Vorgeschlagene Umstrukturierung
Meiner Meinung nach ist ein Array in diesem Fall besser, da Sie mehrere Objekte desselben Typs speichern und wir keinen Zugriff darauf mit einem Schlüssel benötigen. Gibt es einen Grund, warum Sie ein Objekt gewählt haben? (Vielleicht übersehe ich hier etwas?)
Es könnte eine gute Idee sein,
renderPostaus der zurückgegebenen Klasse zu entfernen, da dies eine Methode sein wird, die außerhalb der Render-Funktion verwendet werden kann. Wir müssen Posts nur als Teil der ursprünglichen Render-Funktion rendern. Mit anderen Worten, Sie könnten darauf von außen zugreifen – und da kein Bedarf besteht, darauf zuzugreifen, sollte sie wahrscheinlich nicht als Methode deklariert werden. Schließlich muss kein Schlüssel an einen Index übergeben werden. Wenn Sie eine Kennung benötigen, können Sie das gesamte Post-Objekt übergeben. (poststattpost.data)Ah ja, und Raito Bezarius hat einen guten Punkt bezüglich der Mutation des Zustands. Die `setState`-Funktion sollte immer der direkten Zuweisung des Zustands vorgezogen werden. (Auch Entschuldigung für den schlecht formatierten Code. Mir war nicht bewusst, dass Leerzeichen so funktionieren, wie sie es hier tun!)