Ich habe zwei Komponenten.
- Übergeordnete Komponente
- Untergeordnete Komponente
Ich habe versucht, die Methode des Kindes von Parent aufzurufen. Ich habe es auf diese Weise versucht, konnte aber kein Ergebnis erzielen
class Parent extends Component {
render() {
return (
<Child>
<button onClick={Child.getAlert()}>Click</button>
</Child>
);
}
}
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
Gibt es eine Möglichkeit, die Methode des Kindes vom Elternteil aufzurufen?
Hinweis: Untergeordnete und übergeordnete Komponenten befinden sich in zwei verschiedenen Dateien
javascript
reactjs
N8FURY
quelle
quelle
Antworten:
Lassen Sie mich zunächst ausdrücken, dass dies im Allgemeinen nicht der richtige Weg ist, um Dinge im React-Land zu erledigen. Normalerweise möchten Sie die Funktionalität an Kinder in Requisiten weitergeben und Benachrichtigungen von Kindern in Ereignissen weitergeben (oder noch besser :)
dispatch
.Wenn Sie jedoch eine zwingende Methode für eine untergeordnete Komponente verfügbar machen müssen , können Sie refs verwenden . Denken Sie daran, dass dies eine Notluke ist und normalerweise anzeigt, dass ein besseres Design verfügbar ist.
Verwenden von Hooks und Funktionskomponenten (
>= [email protected]
)Dokumentation für
useImperativeHandle()
ist hier :Verwenden von Klassenkomponenten (
>= [email protected]
)Legacy API (
<= [email protected]
)Aus historischen Gründen ist hier der auf Rückrufen basierende Stil, den Sie mit React-Versionen vor 16.3 verwenden würden:
quelle
connect
eine Komponente höherer Ordnung zurückgegeben wird, die Ihre ursprüngliche Instanz umschließt. Sie müssengetWrappedInstance()
zuerst die angeschlossene Komponente aufrufen , um Ihre ursprüngliche Komponente zu erhalten. Dann können Sie Instanzmethoden dafür aufrufen.componentWillReceiveProps
, und dieses als Auslöser zu verwenden.Sie können hier ein anderes Muster verwenden:
Sie legen die
clickChild
Methode des Elternteils fest, wenn das Kind bereitgestellt wird. Auf diese Weise wird beim Klicken auf die Schaltfläche im übergeordneten Element aufgerufen,clickChild
welches das untergeordnete Element anruftgetAlert
.Dies funktioniert auch, wenn Ihr Kind mit eingewickelt ist,
connect()
sodass Sie dengetWrappedInstance()
Hack nicht benötigen .Beachten Sie, dass Sie nicht
onClick={this.clickChild}
in Eltern verwenden können, da beim Rendern von Eltern Kinder nicht gemountet sind und daherthis.clickChild
noch nicht zugewiesen sind. Die VerwendungonClick={() => this.clickChild()}
ist in Ordnung, da beim Klicken die Schaltflächethis.clickChild
bereits zugewiesen sein sollte.quelle
_this2.clickChild is not a function
verstehe warum?https://facebook.github.io/react/tips/expose-component-functions.html Weitere Antworten finden Sie hier. Rufen Sie Methoden zum Reagieren untergeordneter Komponenten auf
Wenn Sie sich die Refs der "Grund" -Komponente ansehen, brechen Sie die Kapselung und machen es unmöglich, diese Komponente zu refaktorieren, ohne alle verwendeten Stellen sorgfältig zu untersuchen. Aus diesem Grund empfehlen wir dringend, Refs als privat für eine Komponente zu behandeln, ähnlich wie bei state.
Im Allgemeinen sollten Daten über Requisiten an den Baum weitergegeben werden. Es gibt einige Ausnahmen (z. B. das Aufrufen von .focus () oder das Auslösen einer einmaligen Animation, die den Status nicht wirklich "ändert"), aber jedes Mal, wenn Sie eine Methode namens "set" verfügbar machen, sind dies normalerweise Requisiten eine bessere Wahl. Versuchen Sie, es so zu gestalten, dass sich die innere Eingabekomponente um ihre Größe und ihr Aussehen kümmert, damit keiner ihrer Vorfahren dies tut.
quelle
Alternative Methode mit useEffect:
Elternteil:
Kinder:
quelle
Wir können refs auch anders verwenden
Wir werden ein übergeordnetes Element erstellen, es wird eine
<Child/>
Komponente rendern . Wie Sie sehen können, müssen Sie für die zu rendernde Komponente das ref- Attribut hinzufügen und einen Namen dafür angeben.Dann
triggerChildAlert
greift die in der übergeordneten Klasse befindliche Funktion auf die refs-Eigenschaft dieses Kontexts zu (wenn dietriggerChildAlert
Funktion ausgelöst wird, greift sie auf die untergeordnete Referenz zu und verfügt über alle Funktionen des untergeordneten Elements).Nun sieht die untergeordnete Komponente, wie sie zuvor theoretisch entworfen wurde, folgendermaßen aus:
Hier ist der Quellcode -
Hope wird Ihnen helfen!
quelle
Wenn Sie dies einfach tun, weil Sie möchten, dass das Kind seinen Eltern ein wiederverwendbares Merkmal zur Verfügung stellt, können Sie dies stattdessen mit Render-Requisiten tun .
Diese Technik stellt die Struktur tatsächlich auf den Kopf. Das
Child
schließt jetzt das Elternteil ein, also habe ich esAlertTrait
unten umbenannt. Ich habe den NamenParent
für Kontinuität beibehalten , obwohl es jetzt nicht wirklich ein Elternteil ist.In diesem Fall bietet das AlertTrait eine oder mehrere Eigenschaften, die es als Requisiten an die Komponente weitergibt, die es in seiner
renderComponent
Requisite erhalten hat.Der Elternteil erhält
doAlert
als Requisite und kann ihn bei Bedarf anrufen.(Aus Gründen der Übersichtlichkeit habe ich die Requisite
renderComponent
im obigen Beispiel aufgerufen. In den oben verlinkten React-Dokumenten wird sie jedoch nur aufgerufenrender
.)Die Trait-Komponente kann in ihrer Renderfunktion Dinge um das übergeordnete Element rendern, aber sie rendert nichts innerhalb des übergeordneten Elements. Tatsächlich könnte es Dinge innerhalb des
renderChild
übergeordneten Elements rendern, wenn es dem übergeordneten Element eine andere Requisite (z. B. ) übergibt, die das übergeordnete Element dann während seiner Rendermethode verwenden könnte.Dies unterscheidet sich etwas von dem, was das OP verlangt hat, aber einige Leute könnten hier landen (wie wir), weil sie ein wiederverwendbares Merkmal erstellen wollten und dachten, dass eine untergeordnete Komponente ein guter Weg ist, dies zu tun.
quelle
this.clickChild = click
aber Ihre mehreren Stoppuhren mehrere Funktionen übergeben würden, sodass Sie alle speichern müssten:this.watchRestartFuncs[watchId] = restartWatch
Sie können dies auf diese Weise leicht erreichen
Schritte-
Greifen Sie von der untergeordneten Komponente mit Requisiten auf diese Variable zu und führen Sie die gewünschte Methode aus, indem Sie eine if-Bedingung haben.
quelle
Ich benutze
useEffect
Hook, um die Kopfschmerzen zu überwinden, die damit verbunden sind. Jetzt übergebe ich eine Variable wie folgt an ein Kind:quelle
Ich war mit keiner der hier vorgestellten Lösungen zufrieden. Es gibt tatsächlich eine sehr einfache Lösung, die mit reinem Javascript durchgeführt werden kann, ohne auf andere React-Funktionen als das grundlegende Requisitenobjekt angewiesen zu sein - und die Ihnen den Vorteil bietet, in beide Richtungen zu kommunizieren (Eltern -> Kind, Kind -> Eltern). Sie müssen ein Objekt von der übergeordneten Komponente an die untergeordnete Komponente übergeben. Dieses Objekt ist das, was ich als "bidirektionale Referenz" oder kurz biRef bezeichne. Grundsätzlich enthält das Objekt einen Verweis auf Methoden im übergeordneten Objekt, die das übergeordnete Objekt verfügbar machen möchte. Die untergeordnete Komponente hängt Methoden an das Objekt an, das die übergeordnete Komponente aufrufen kann. Etwas wie das:
Der andere Vorteil dieser Lösung besteht darin, dass Sie dem übergeordneten und dem untergeordneten Element viel mehr Funktionen hinzufügen können, während Sie diese mit nur einer einzigen Eigenschaft vom übergeordneten Element an das untergeordnete Element übergeben.
Eine Verbesserung gegenüber dem obigen Code besteht darin, die übergeordneten und untergeordneten Funktionen nicht direkt zum biRef-Objekt, sondern zu Untermitgliedern hinzuzufügen. Übergeordnete Funktionen sollten einem Mitglied namens "parent" hinzugefügt werden, während die untergeordneten Funktionen einem Mitglied namens "child" hinzugefügt werden sollten.
Wenn Sie übergeordnete und untergeordnete Funktionen in separate Elemente des biRef-Objekts einfügen, haben Sie eine saubere Trennung zwischen den beiden und können leicht erkennen, welche zu Eltern oder untergeordneten Elementen gehören. Es hilft auch zu verhindern, dass eine untergeordnete Komponente versehentlich eine übergeordnete Funktion überschreibt, wenn in beiden dieselbe Funktion angezeigt wird.
Eine letzte Sache ist, dass, wenn Sie bemerken, die übergeordnete Komponente das biRef-Objekt mit var erstellt, während die untergeordnete Komponente über das Requisitenobjekt darauf zugreift. Es könnte verlockend sein, das biRef-Objekt im übergeordneten Objekt nicht zu definieren und von seinem übergeordneten Objekt über seinen eigenen Requisitenparameter darauf zuzugreifen (was in einer Hierarchie von UI-Elementen der Fall sein kann). Dies ist riskant, da das Kind möglicherweise denkt, dass eine Funktion, die es dem Elternteil aufruft, dem Elternteil gehört, wenn es tatsächlich einem Großelternteil gehört. Daran ist nichts auszusetzen, solange Sie sich dessen bewusst sind. Sofern Sie keinen Grund haben, eine Hierarchie über eine Eltern-Kind-Beziehung hinaus zu unterstützen, ist es am besten, das biRef in Ihrer übergeordneten Komponente zu erstellen.
quelle
Sie können Inheritance Inversion durchführen (siehe hier: https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e ). Auf diese Weise haben Sie Zugriff auf die Instanz der Komponente, die Sie verpacken würden (somit können Sie auf deren Funktionen zugreifen).
quelle
Ich denke, dass der einfachste Weg, Methoden aufzurufen, darin besteht, eine Anforderung für die untergeordnete Komponente festzulegen. Sobald das Kind die Anforderung bearbeitet, ruft es eine Rückrufmethode auf, um die Anforderung zurückzusetzen.
Der Rücksetzmechanismus ist erforderlich, um dieselbe Anforderung mehrmals nacheinander senden zu können.
In der übergeordneten Komponente
In der Rendermethode des übergeordneten Elements:
Der Elternteil benötigt zwei Methoden, um mit seinem Kind in zwei Richtungen zu kommunizieren.
In der untergeordneten Komponente
Das Kind aktualisiert seinen internen Status und kopiert die Anforderung von den Requisiten.
Anschließend wird die Anforderung verarbeitet und der Reset an das übergeordnete Element gesendet:
quelle
Eine andere Möglichkeit, eine untergeordnete Funktion vom übergeordneten Element aus auszulösen, besteht darin, die
componentDidUpdate
Funktion in der untergeordneten Komponente zu verwenden. Ich gebe eine RequisitetriggerChildFunc
von Eltern an Kind weiter, was anfangs so istnull
. Der Wert ändert sich in eine Funktion, wenn auf die Schaltfläche geklickt wird und Child dies ändertcomponentDidUpdate
und seine eigene interne Funktion aufruft.Da prop
triggerChildFunc
zu einer Funktion wechselt, erhalten wir auch einen Rückruf an das übergeordnete Element. Wenn Parent nicht wissen muss, wann die Funktion aufgerufen wird, kann sich der WerttriggerChildFunc
beispielsweise vonnull
zu änderntrue
.CodePen: https://codepen.io/calsal/pen/NWPxbJv?editors=1010
quelle
Hier meine Demo: https://stackblitz.com/edit/react-dgz1ee?file=styles.css
Ich verwende
useEffect
, um die Methoden der untergeordneten Komponente aufzurufen. Ich habe es mit versucht,Proxy and Setter_Getter
aber soruseEffect
scheint die bequemere Möglichkeit zu sein, eine untergeordnete Methode vom Elternteil aufzurufen. UmProxy and Setter_Getter
es zu verwenden , scheint es eine gewisse Subtilität zu geben, die zuerst überwunden werden muss, da das zuerst gerenderte Element durch die Spezifität des Objekts ein objektähnliches Element istref.current return => <div/>
. ÜberuseEffect
auf diesen Ansatz können Sie auch den Status der Eltern festlegen, je nachdem, was Sie mit den Kindern tun möchten.In dem von mir bereitgestellten Link der Demo finden Sie meinen vollständigen ReactJS-Code mit meinen Entwürfen, damit Sie den Workflow meiner Lösung schätzen können.
Hier versorge ich Sie nur mit dem entsprechenden Code für das ReactJS-Snippet. ::
quelle
Wir freuen uns über einen benutzerdefinierten Haken, den wir anrufen
useCounterKey
. Es wird nur ein CounterKey oder ein Schlüssel eingerichtet, der von Null an zählt. Die zurückgegebene Funktion setzt die Taste zurück (dh inkrementieren). (Ich glaube, dies ist der idiomatischste Weg in React , um eine Komponente zurückzusetzen - drücken Sie einfach die Taste.)Dieser Hook funktioniert jedoch auch in allen Situationen, in denen Sie eine einmalige Nachricht an den Client senden möchten, um etwas zu tun. Zum Beispiel verwenden wir es, um ein Steuerelement im Kind auf ein bestimmtes übergeordnetes Ereignis zu fokussieren - es fokussiert nur automatisch, wenn der Schlüssel aktualisiert wird. (Wenn mehr Requisiten benötigt werden, können diese vor dem Zurücksetzen des Schlüssels festgelegt werden, damit sie verfügbar sind, wenn das Ereignis eintritt.)
Diese Methode hat eine gewisse Lernkurve, da sie nicht so einfach ist wie ein typischer Ereignishandler, aber es scheint die idiomatischste Art zu sein, dies in React zu handhaben, die wir gefunden haben (da Tasten bereits auf diese Weise funktionieren). Auf jeden Fall offen für Feedback zu dieser Methode, aber es funktioniert gut!
Beispielverwendungen:
( Dank an Kent Dodds für das counterKey-Konzept .)
quelle
Hier ist ein Fehler? zu beachten: Ich stimme der Lösung von rossipedia mit forwardRef, useRef, useImperativeHandle zu
Es gibt einige Fehlinformationen online, die besagen, dass Refs nur aus React Class-Komponenten erstellt werden können. Sie können jedoch tatsächlich Funktionskomponenten verwenden, wenn Sie die oben genannten Hooks verwenden. Ein Hinweis, die Hooks funktionierten nur für mich, nachdem ich die Datei so geändert hatte, dass sie beim Exportieren der Komponente nicht mit Router () verwendet wurde. Dh eine Abwechslung von
stattdessen sein
Im Nachhinein wird withRouter () für eine solche Komponente ohnehin nicht benötigt, aber normalerweise schadet es nichts, wenn es vorhanden ist. Mein Anwendungsfall ist, dass ich eine Komponente erstellt habe, um eine Tabelle zum Anzeigen und Bearbeiten von Konfigurationswerten zu erstellen. und ich wollte in der Lage sein, dieser untergeordneten Komponente anzuweisen, ihre Statuswerte zurückzusetzen, wenn die Schaltfläche "Zurücksetzen" des übergeordneten Formulars gedrückt wurde. UseRef () würde ref oder ref.current (immer null) nicht richtig abrufen, bis ich withRouter () aus der Datei entfernt habe, die meine untergeordnete Komponente TableConfig enthält
quelle