Gibt es nicht eine einfache Möglichkeit, ein Kind props
mithilfe von Ereignissen in React.js an seine Eltern zu übergeben?
var Child = React.createClass({
render: function() {
<a onClick={this.props.onClick}>Click me</a>
}
});
var Parent = React.createClass({
onClick: function(event) {
// event.component.props ?why is this not available?
},
render: function() {
<Child onClick={this.onClick} />
}
});
Ich weiß, dass Sie gesteuerte Komponenten verwenden können, um den Wert eines Eingangs zu übergeben, aber es wäre schön, das gesamte Kit n 'Kaboodle zu übergeben. Manchmal enthält die untergeordnete Komponente eine Reihe von Informationen, die Sie lieber nicht nachschlagen müssen.
Vielleicht gibt es eine Möglichkeit, die Komponente an das Ereignis zu binden?
UPDATE - 01.09.2015
Nachdem ich React über ein Jahr lang verwendet habe und von Sebastien Lorbers Antwort beflügelt wurde, bin ich zu dem Schluss gekommen, dass das Übergeben von untergeordneten Komponenten als Argumente für Funktionen in Eltern weder React noch eine gute Idee ist. Ich habe die Antwort gewechselt.
quelle
Antworten:
Bearbeiten : In den Endbeispielen finden Sie aktualisierte ES6-Beispiele.
Diese Antwort behandelt einfach den Fall einer direkten Eltern-Kind-Beziehung. Wenn Eltern und Kind möglicherweise viele Vermittler haben, überprüfen Sie diese Antwort .
Andere Lösungen verfehlen den Punkt
Während sie noch gut funktionieren, fehlt anderen Antworten etwas sehr Wichtiges.
Der Elternteil hat bereits diese Kinderstütze! : Wenn das Kind eine Requisite hat, dann deshalb, weil sein Elternteil dem Kind diese Requisite zur Verfügung gestellt hat! Warum soll das Kind die Requisite an die Eltern zurückgeben, während die Eltern diese Requisite offensichtlich bereits haben?
Bessere Umsetzung
Kind : Es muss wirklich nicht komplizierter sein.
Eltern mit einem einzelnen Kind : Verwenden des Werts, der an das Kind übergeben wird
JsFiddle
Elternteil mit Liste der Kinder : Sie haben immer noch alles, was Sie brauchen, auf dem Elternteil und müssen das Kind nicht komplizierter machen.
JsFiddle
Es ist auch möglich, zu verwenden
this.handleChildClick.bind(null,childIndex)
und dann zu verwendenthis.state.childrenData[childIndex]
Beachten Sie, dass wir mit einem
null
Kontext binden, da React andernfalls eine Warnung bezüglich seines Autobindungssystems ausgibt . Die Verwendung von null bedeutet, dass Sie den Funktionskontext nicht ändern möchten. Siehe auch .Über Kapselung und Kopplung in anderen Antworten
Dies ist für mich eine schlechte Idee in Bezug auf Kopplung und Einkapselung:
Verwenden von Requisiten : Wie oben erläutert, haben Sie die Requisiten bereits im übergeordneten Element, sodass es sinnlos ist, die gesamte untergeordnete Komponente für den Zugriff auf Requisiten zu übergeben.
Verwenden von Refs : Sie haben bereits das Klickziel im Ereignis, und in den meisten Fällen reicht dies aus. Außerdem hätten Sie einen Ref direkt für das Kind verwenden können:
Und greifen Sie mit auf den DOM-Knoten im übergeordneten Knoten zu
In fortgeschritteneren Fällen, in denen Sie auf mehrere Refs des untergeordneten Elements im übergeordneten Element zugreifen möchten, kann das untergeordnete Element alle dom-Knoten direkt im Rückruf übergeben.
Die Komponente verfügt über eine Schnittstelle (Requisiten), und der Elternteil sollte nichts über die innere Arbeitsweise des Kindes annehmen, einschließlich seiner inneren DOM-Struktur oder der DOM-Knoten, für die er Refs deklariert. Ein Elternteil, der eine Referenz eines Kindes verwendet, bedeutet, dass Sie die beiden Komponenten eng miteinander verbinden.
Um das Problem zu veranschaulichen, nehme ich dieses Zitat über das Shadow DOM , das in Browsern verwendet wird, um Dinge wie Schieberegler, Bildlaufleisten, Videoplayer zu rendern ...:
Das Problem besteht darin, dass es sehr schwierig ist, das untergeordnete Element zu überarbeiten, ohne dass sich dies auf das übergeordnete Element auswirkt, wenn Sie die untergeordneten Implementierungsdetails in das übergeordnete Element übertragen. Dies bedeutet, dass dies als Bibliotheksautor (oder als Browser-Editor mit Shadow DOM) sehr gefährlich ist, da Sie dem Client zu viel Zugriff gewähren, was es sehr schwierig macht, Code zu aktualisieren, ohne die Retrokompatibilität zu beeinträchtigen.
Wenn Chrome seine Bildlaufleiste implementiert hat, mit der der Client auf die inneren Domänenknoten dieser Bildlaufleiste zugreifen kann, bedeutet dies, dass der Client möglicherweise die Möglichkeit hat, diese Bildlaufleiste einfach zu beschädigen, und dass Apps leichter beschädigt werden, wenn Chrome nach dem Refactoring die automatische Aktualisierung durchführt Bildlaufleiste ... Stattdessen bieten sie nur Zugriff auf einige sichere Dinge wie das Anpassen einiger Teile der Bildlaufleiste mit CSS.
Über die Verwendung von etwas anderem
Die gesamte Komponente in der Callback - Passing ist gefährlich und Anfänger Entwickler führen können sehr seltsame Dinge zu tun , wie der Aufruf
childComponent.setState(...)
oderchildComponent.forceUpdate()
, oder es neue Variablen, innerhalb des übergeordneten, so dass die ganze app viel schwieriger zu Grund , sich über die Zuordnung.Bearbeiten: ES6-Beispiele
Da viele Leute jetzt ES6 verwenden, finden Sie hier dieselben Beispiele für die ES6-Syntax
Das Kind kann sehr einfach sein:
Das Elternteil kann entweder eine Klasse sein (und es kann schließlich den Staat selbst verwalten, aber ich gebe es hier als Requisiten weiter:
Es kann aber auch vereinfacht werden, wenn der Status nicht verwaltet werden muss:
JsFiddle
PERF-WARNUNG (gilt für ES5 / ES6): Wenn Sie
PureComponent
oder verwendenshouldComponentUpdate
, werden die oben genannten Implementierungen nicht standardmäßig optimiertonClick={e => doSomething()}
, da sie während der Renderphase verwendet oder direkt gebunden werden, da bei jedem Rendern des übergeordneten Elements eine neue Funktion erstellt wird. Wenn dies ein perfekter Engpass in Ihrer App ist, können Sie die Daten an die untergeordneten Elemente übergeben und sie innerhalb des "stabilen" Rückrufs (der für die übergeordnete Klasse festgelegt und an den Klassenkonstruktor gebunden istthis
) erneut einfügen, damit diePureComponent
Optimierung aktiviert werden kann, oder Sie Sie können Ihre eigenen implementierenshouldComponentUpdate
und den Rückruf in der Requisitenvergleichsprüfung ignorieren.Sie können auch die Recompose- Bibliothek verwenden, die Komponenten höherer Ordnung bereitstellt, um fein abgestimmte Optimierungen zu erzielen:
In diesem Fall können Sie die untergeordnete Komponente optimieren, indem Sie Folgendes verwenden:
quelle
props
. Zustimmen?How do I know which of my children was chosen among a group?
Dies ist nicht wirklich Teil der ursprünglichen Frage, aber ich habe die Lösung in meine Antwort aufgenommen. Im Gegensatz zu Ihrer Bearbeitung ist es meines Erachtens nicht erforderlich, das untergeordnete Element zu ändern, selbst wenn Sie sich mit einer Liste befassen, da Sie diesebind
direkt im übergeordneten Element verwenden können.onClick={this.handleChildClick.bind(null,childData)}
Sie über Autobindung erwähnt haben, gilt dies auch jetzt noch, da React nicht im Klassenmodell enthalten ist . Ich habe viel gelesen, aber dieser Teil verwirrt mich immer noch. Ich verwende ES6class model
durch die Art und Weise, also habe ichnull
aufthis
und mein Code scheinen immer noch zu arbeiten. Wie würden Sie diesen Teil Ihres Codes in einen ES6-Stil übersetzen?Update (01.09.15): Das OP hat diese Frage zu einem beweglichen Ziel gemacht. Es wurde erneut aktualisiert. Daher fühle ich mich dafür verantwortlich, meine Antwort zu aktualisieren.
Zunächst eine Antwort auf Ihr Beispiel:
Ja, das ist möglich.
Sie können dies lösen, indem Sie Child's
onClick
wie folgt aktualisierenthis.props.onClick.bind(null, this)
:Der Ereignishandler in Ihrem übergeordneten Element kann dann wie folgt auf die Komponente und das Ereignis zugreifen:
JSBin-Schnappschuss
Aber die Frage selbst ist irreführend
Eltern kennen bereits Kinder
props
.Dies ist im angegebenen Beispiel nicht klar, da tatsächlich keine Requisiten bereitgestellt werden. Dieser Beispielcode unterstützt möglicherweise die gestellte Frage besser:
In diesem Beispiel wird viel deutlicher, dass Sie bereits wissen, was die Requisiten von Child sind.
JSBin-Schnappschuss
Wenn es wirklich darum geht, die Requisiten eines Kindes zu benutzen ...
Wenn es wirklich darum geht, die Requisiten eines Kindes zu verwenden, können Sie jegliche Verbindung mit Child insgesamt vermeiden.
JSX verfügt über eine API für Spread-Attribute, die ich häufig für Komponenten wie Child verwende. Es nimmt alle
props
und wendet sie auf eine Komponente an. Kind würde so aussehen:So können Sie die Werte direkt im übergeordneten Element verwenden:
JSBin-Schnappschuss
Es ist keine zusätzliche Konfiguration erforderlich, wenn Sie zusätzliche untergeordnete Komponenten anschließen
JSBin-Schnappschuss
Aber ich vermute, dass dies nicht Ihr eigentlicher Anwendungsfall ist. Also lasst uns weiter graben ...
Ein robustes praktisches Beispiel
Die generische Natur des bereitgestellten Beispiels ist schwer zu besprechen. Ich habe eine Komponente erstellt, die eine praktische Verwendung für die obige Frage demonstriert und in einer sehr reaktiven Weise implementiert wurde Weise :
Arbeitsbeispiel für DTServiceCalculator
DTServiceCalculator Repo
Diese Komponente ist ein einfacher Service-Rechner. Sie stellen ihm eine Liste von Diensten (mit Namen und Preisen) zur Verfügung und er berechnet die Summe der ausgewählten Preise.
Kinder sind selig unwissend
ServiceItem
ist die untergeordnete Komponente in diesem Beispiel. Es gibt nicht viele Meinungen über die Außenwelt. Es sind einige Requisiten erforderlich , von denen eine eine Funktion ist, die beim Klicken aufgerufen werden muss.<div onClick={this.props.handleClick.bind(this.props.index)} />
Es wird nichts anderes getan, als den bereitgestellten
handleClick
Rückruf mit der bereitgestelltenindex
[ Quelle ] aufzurufen .Eltern sind Kinder
DTServicesCalculator
ist die übergeordnete Komponente ist dieses Beispiel. Es ist auch ein Kind. Lass uns nachsehen.DTServiceCalculator
Erstellt eine Liste der untergeordneten KomponentenServiceItem
und stellt ihnen Requisiten zur Verfügung [ Quelle ]. Es ist die übergeordnete Komponente von,ServiceItem
aber es ist die untergeordnete Komponente der Komponente, die die Liste übergibt. Es besitzt nicht die Daten. Daher delegiert es erneut die Behandlung der Komponente an die Quelle der übergeordneten Komponente<ServiceItem chosen={chosen} index={i} key={id} price={price} name={name} onSelect={this.props.handleServiceItem} />
handleServiceItem
erfasst den vom Kind übergebenen Index und stellt ihn seinem übergeordneten [ Quelle ] zur Verfügung.Die Besitzer wissen alles
Das Konzept der „Eigentümerschaft“ spielt in React eine wichtige Rolle. Ich empfehle mehr darüber zu lesen hier .
In dem Beispiel, das ich gezeigt habe, delegiere ich die Behandlung eines Ereignisses so lange im Komponentenbaum, bis wir zu der Komponente gelangen, der der Status gehört.
Wenn wir endlich dort ankommen, behandeln wir die Auswahl / Abwahl des Status wie folgt: [ Quelle ]:
Fazit
Versuchen Sie, Ihre äußersten Komponenten so undurchsichtig wie möglich zu halten. Stellen Sie sicher, dass sie nur sehr wenige Einstellungen dazu haben, wie eine übergeordnete Komponente sie implementieren möchte.
Achten Sie darauf, wem die von Ihnen manipulierten Daten gehören. In den meisten Fällen müssen Sie die Ereignisbehandlung im Baum an die Komponente delegieren, die diesen Status besitzt .
Nebenbei: Das Flux-Muster ist ein guter Weg, um diese Art der erforderlichen Verbindung in Apps zu reduzieren.
quelle
Parent
könnte es sich um eine solche Controller-Ansicht handeln, währendChild
es sich nur um eine dumme Ansicht (Komponente) handelt. Nur Controller-Views sollten Kenntnisse über die Anwendung haben. In diesem Fall würde passieren Sie noch die Aktion aus ,Parent
umChild
als Stütze. In Bezug auf die Aktion selbst verfügt Flux über ein stark vorgeschriebenes Muster für die Interaktion zwischen Aktionen, um Ansichten zu aktualisieren. facebook.github.io/flux/docs/…onClick={this.onClick.bind(null, this.state.text)}
Keine Notwendigkeit, den Status zu binden, da der Elternteil dies hat. also wird einfachonClick={this.onClick}
funktionieren. woonClick = ()=>{const text = this.state.text;..}
in ElternEs scheint, dass es eine einfache Antwort gibt. Bedenken Sie:
Der Schlüssel ruft das vom übergeordneten Element
bind(null, this)
übergebenethis.props.onClick
Ereignis auf. Jetzt akzeptiert die onClick-Funktion Argumentecomponent
UNDevent
. Ich denke, das ist das Beste von allen Welten.UPDATE: 01.09.2015
Dies war eine schlechte Idee: Es war nie ein guter Weg, die Implementierungsdetails des Kindes an die Eltern weiterzuleiten. Siehe Sebastien Lorbers Antwort.
quelle
this
die Funktion gebunden (die ohnehin nicht benötigt wird), und das zweite Argument wird beim Aufruf von onClick als erstes Argument vorangestellt.Die Frage ist, wie Argumente von der untergeordneten an die übergeordnete Komponente übergeben werden. Dieses Beispiel ist einfach zu verwenden und zu testen:
Schauen Sie sich JSFIDDLE an
quelle
Grundsätzlich verwenden Sie Requisiten, um Informationen an und von Kind und Eltern zu senden.
Lassen Sie mich zu all den wunderbaren Antworten ein einfaches Beispiel geben, in dem die Übergabe von Werten von der untergeordneten an die übergeordnete Komponente in React erläutert wird
App.js.
Header.js
Main.js
Jetzt können Sie Werte von Ihrem Client an den Server übergeben.
Schauen Sie sich die Änderungsfunktion in der Header.js an
Auf diese Weise übertragen Sie Werte in die Requisiten vom Client zum Server
quelle
Hier ist eine einfache 3-Schritt-ES6-Implementierung unter Verwendung der Funktionsbindung im übergeordneten Konstruktor. Dies ist der erste Weg, den das offizielle Reaktionstutorial empfiehlt (es gibt auch eine Syntax für Felder öffentlicher Klassen, die hier nicht behandelt wird). All diese Informationen finden Sie hier https://reactjs.org/docs/handling-events.html
Binden von Elternfunktionen, damit Kinder sie anrufen können (und Daten an die Eltern weitergeben !: D)
Übergeordnete Funktion
Übergeordneter Konstruktor
Requisite an Kind übergeben
Untergeordneter Ereignisanruf
quelle
Dies ist ein Beispiel ohne Verwendung des onClick-Ereignisses. Ich übergebe dem Kind einfach eine Rückruffunktion durch Requisiten. Mit diesem Rückruf sendet der untergeordnete Anruf auch Daten zurück. Die Beispiele in den Dokumenten haben mich inspiriert .
Kleines Beispiel (dies ist in einer tsx-Datei, daher müssen Requisiten und Zustände vollständig deklariert werden. Ich habe einige Logik aus den Komponenten gelöscht, damit es weniger Code gibt).
* Update: Wichtig ist, dies an den Rückruf zu binden, andernfalls hat der Rückruf den Umfang des untergeordneten und nicht des übergeordneten Rückrufs. Einziges Problem: Es ist der "alte" Elternteil ...
SymptomChoser ist der Elternteil:
Symptom ist das Kind (in den Requisiten des Kindes habe ich die Rückruffunktion deklariert, in der Funktion selectedSymptom wird der Rückruf aufgerufen):
quelle