Dies mag die Grenze zwischen verantwortungsbewusst und eigensinnig überschreiten, aber ich gehe hin und her, wie eine ReactJS-Komponente mit zunehmender Komplexität strukturiert werden kann und eine Richtung verwenden könnte.
Aus AngularJS kommend möchte ich mein Modell als Eigenschaft an die Komponente übergeben und die Komponente das Modell direkt ändern lassen. Oder sollte ich das Modell in verschiedene state
Eigenschaften aufteilen und beim Zusammensenden wieder zusammenstellen? Was ist der ReactJS-Weg?
Nehmen Sie das Beispiel eines Blogpost-Editors. Der Versuch, das Modell direkt zu ändern, sieht folgendermaßen aus:
var PostEditor = React.createClass({
updateText: function(e) {
var text = e.target.value;
this.props.post.text = text;
this.forceUpdate();
},
render: function() {
return (
<input value={this.props.post.text} onChange={this.updateText}/>
<button onClick={this.props.post.save}/>Save</button>
);
}
});
Welches scheint falsch.
Ist es eher die React-Methode, um unsere text
Modelleigenschaft zu state
erstellen und sie vor dem Speichern wieder in das Modell zu kompilieren?
var PostEditor = React.createClass({
getInitialState: function() {
return {
text: ""
};
},
componentWillMount: function() {
this.setState({
text: this.props.post.text
});
},
updateText: function(e) {
this.setState({
text: e.target.value
});
},
savePost: function() {
this.props.post.text = this.state.text;
this.props.post.save();
},
render: function() {
return (
<input value={this.state.text} onChange={this.updateText}/>
<button onClick={this.savePost}/>Save</button>
);
}
});
Dies erfordert keinen Aufruf von this.forceUpdate()
, aber wenn das Modell wächst (ein Beitrag kann einen Autor, einen Betreff, Tags, Kommentare, Bewertungen usw. enthalten), wird die Komponente sehr kompliziert.
text
, wir haben anstelle eines Feldes einesetText
Methode, die die Validierung und einige andere Dinge ausführt. Ich kann sehen, dass Methode (2) funktioniert, wenn siesetText
rein ist und eine brandneue Instanz des Modells zurückgibt. WennsetText
wir jedoch nur den inneren Zustand aktualisieren, müssten wir immer noch aufrufenforceUpdate
, oder?forceUpdate
, aber an diesem Punkt "lecken" Sie aus React heraus. Es ist möglicherweise besser, einensetState()
Rückruf an das undurchsichtige Modell zu übergeben, um zu vermeiden, dass erneutes Rendern manuell ausgelöst werden muss.Aktualisierung 2016: Die Reaktion wurde geändert und die Erklärung "Requisiten gegen Status" wurde sehr einfach. Wenn eine Komponente Daten ändern muss, versetzen Sie sie in einen Zustand, andernfalls in Requisiten. Weil Requisiten schreibgeschützt sind jetzt .
Was ist der genaue Unterschied zwischen Requisiten und Staat?
Sie können eine gute Erklärung finden hier (Vollversion)
quelle
setProps
ist veraltet und sollte nicht verwendet werden. Durch Ersetzen wird die Komponente erneut gerendert und React kann die Unterschiede behandeln.Aus React doc
Von TrySpace : Wenn Requisiten (oder Status) aktualisiert werden (über setProps / setState oder Parent), wird die Komponente ebenfalls neu gerendert.
quelle
Eine Lesung aus Thinking in React :
quelle
Ich bin nicht sicher, ob ich Ihre Frage beantworte, aber ich habe festgestellt, dass das Container- / Komponentenmuster besonders in einer großen / wachsenden Anwendung unglaublich gut funktioniert.
Im Wesentlichen haben Sie zwei React-Komponenten:
Beispiel
NB Dieses Beispiel ist wahrscheinlich zu einfach, um die Vorteile dieses Musters zu veranschaulichen, da es für einen so einfachen Fall ziemlich ausführlich ist.
Leistungen
Indem Sie Anzeigelogik und Daten- / Statusverwaltung getrennt halten, haben Sie eine wiederverwendbare Anzeigekomponente, die:
Sie haben auch eine Containerkomponente, die sich um die gesamte externe Kommunikation kümmert. Dies sollte es einfacher machen, flexibel auf den Zugriff auf Ihre Daten zuzugreifen, wenn Sie später ernsthafte Änderungen vornehmen *.
Dieses Muster erleichtert auch das Schreiben und Implementieren von Komponententests erheblich.
Nachdem ich einige Male eine große React-App wiederholt habe, habe ich festgestellt, dass dieses Muster die Dinge relativ schmerzlos macht, insbesondere wenn Sie größere Komponenten mit berechneten Stilen oder komplizierten DOM-Interaktionen haben.
*
InformierenSie sich über dasFlussmusterund werfenSieeinen Blick aufMarty.js, das diese Antwort weitgehend inspiriert hat (und ich habe in letzter Zeit viel verwendet).Redux (und React-Redux ), das dieses Muster sehr gut implementiert.quelle
Ich denke, Sie verwenden ein Anti-Pattern, das Facebook bereits unter diesem Link erklärt hat
Folgendes finden Sie:
Wenn die innere Komponente zum ersten Mal gerendert wird, hat sie {foo: 'bar'} als Wertstütze. Wenn der Benutzer auf den Anker klickt, wird der Status der übergeordneten Komponente auf {value: {foo: 'barbar'}} aktualisiert, wodurch der erneute Rendervorgang der inneren Komponente ausgelöst wird, die {foo: 'barbar'} als empfängt der neue Wert für die Stütze.
Das Problem ist, dass sich die Requisite der inneren Komponente ändert, da die übergeordnete und die innere Komponente einen Verweis auf dasselbe Objekt verwenden, wenn das Objekt in Zeile 2 der onClick-Funktion mutiert wird. Wenn also der Prozess des erneuten Renderns startet und falls ComponentUpdate aufgerufen wird, ist this.props.value.foo gleich nextProps.value.foo, da this.props.value tatsächlich auf dasselbe Objekt wie nextProps.value verweist.
Infolgedessen wird die Benutzeroberfläche nicht von "bar" auf "barbar" aktualisiert, da wir die Änderung an der Requisite verpassen und den Rendering-Prozess kurzschließen.
quelle
Innercomponents
Code posten ?