it-swarm.com.de

Rufen Sie die untergeordnete Methode vom übergeordneten Element auf

Ich habe zwei Komponenten.

  1. Übergeordnete Komponente 
  2. Kindkomponente

Ich habe versucht, die Methode von Child 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 Kindmethode vom Elternteil aufzurufen?

Hinweis: Untergeordnete und übergeordnete Komponenten befinden sich in zwei verschiedenen Dateien 

232
Evo SL

Lassen Sie mich zunächst ausdrücken, dass dies im Allgemeinen nicht der Weg ist, um Dinge in React land. Gewöhnlich was) zu erledigen Sie möchten die Funktionalität an Kinder in Requisiten weitergeben und Benachrichtigungen von Kindern in Ereignissen weitergeben (oder noch besser: dispatch ).

Wenn Sie jedoch eine imperative 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.

Bisher wurden Refs nur für klassenbasierte Komponenten unterstützt. Mit dem Aufkommen von React Hooks ist dies nicht mehr der Fall

Hooks und Funktionskomponenten verwenden (>= [email protected])

import React, { forwardRef, useRef, useImperativeHandle } from 'react';

// We need to wrap component in `forwardRef` in order to gain
// access to the ref object that is assigned using the `ref` prop.
// This ref is passed as the second parameter to the function component.
const Child = forwardRef((props, ref) => {

  // The component instance will be extended
  // with whatever you return from the callback passed
  // as the second argument
  useImperativeHandle(ref, () => ({

    getAlert() {
      alert("getAlert from Child");
    }

  }));

  return <h1>Hi</h1>;
});

const Parent = () => {
  // In order to gain access to the child component instance,
  // you need to assign it to a `ref`, so we call `useRef()` to get one
  const childRef = useRef();

  return (
    <div>
      <Child ref={childRef} />
      <button onClick={() => childRef.current.getAlert()}>Click</button>
    </div>
  );
};

Funktionsbeispiel

Dokumentation für useImperativeHandle() ist hier :

useImperativeHandle passt den Instanzwert an, der für übergeordnete Komponenten verfügbar gemacht wird, wenn ref verwendet wird.

Klassenkomponenten verwenden (>= [email protected])

class Parent extends Component {
  constructor(props) {
    super(props);
    this.child = React.createRef();
  }

  onClick = () => {
    this.child.current.getAlert();
  };

  render() {
    return (
      <div>
        <Child ref={this.child} />
        <button onClick={this.onClick}>Click</button>
      </div>
    );
  }
}

class Child extends Component {
  getAlert() {
    alert('getAlert from Child');
  }

  render() {
    return <h1>Hello</h1>;
  }
}

ReactDOM.render(<Parent />, document.getElementById('root'));

Funktionsbeispiel

Legacy API (<= [email protected])

Aus historischen Gründen ist hier der Callback-basierte Stil, den Sie mit React Versionen vor 16.3 verwenden würden:

const { Component } = React;
const { render } = ReactDOM;

class Parent extends Component {
  render() {
    return (
      <div>
        <Child ref={instance => { this.child = instance; }} />
        <button onClick={() => { this.child.getAlert(); }}>Click</button>
      </div>
    );
  }
}

class Child extends Component {
  getAlert() {
    alert('clicked');
  }

  render() {
    return (
      <h1>Hello</h1>
    );
  }
}


render(
  <Parent />,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>
445
rossipedia

Sie können hier ein anderes Muster verwenden:

class Parent extends Component {
 render() {
  return (
    <div>
      <Child setClick={click => this.clickChild = click}/>
      <button onClick={() => this.clickChild()}>Click</button>
    </div>
  );
 }
}

class Child extends Component {
 constructor(props) {
    super(props);
    this.getAlert = this.getAlert.bind(this);
 }
 componentDidMount() {
    this.props.setClick(this.getAlert);
 }
 getAlert() {
    alert('clicked');
 }
 render() {
  return (
    <h1 ref="hello">Hello</h1>
  );
 }
}

Dabei wird die clickChild-Methode des übergeordneten Objekts festgelegt, wenn das untergeordnete Element gemountet wird. Wenn Sie auf die Schaltfläche im übergeordneten Element klicken, wird auf diese Weise clickChild aufgerufen, die das getAlert des Kindes aufruft.

Dies funktioniert auch, wenn Ihr Kind mit connect () umhüllt ist, sodass Sie den getWrappedInstance () - Hack nicht benötigen.

Beachten Sie, dass Sie onClick = {this.clickChild} im übergeordneten Element nicht verwenden können, da das übergeordnete untergeordnete Element nicht angehängt ist. Dies ist also noch nicht zugewiesen. Verwenden von onClick = {() => this.clickChild ()} ist in Ordnung, da beim Klicken auf die Schaltfläche this.clickChild bereits zugewiesen sein sollte.

68
brickingup

https://facebook.github.io/react/tips/expose-component-functions.html Weitere Antworten finden Sie hier Aufruf von Methoden zu untergeordneten Komponenten von React

Indem Sie in die Refs der "Grund" -Komponente schauen, brechen Sie die Einkapselung und machen es unmöglich, diese Komponente zu refaktorisieren, ohne sorgfältig alle verwendeten Stellen zu untersuchen. Aus diesem Grund empfehlen wir dringend, Refs für eine Komponente zu behandeln, ähnlich wie state.

Im Allgemeinen sollten die 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"). Wenn Sie jedoch eine Methode mit dem Namen "set" freigeben, sind dies normalerweise Requisiten eine bessere Wahl. Versuchen Sie es so zu gestalten, dass sich die innere Eingabekomponente um ihre Größe und ihr Erscheinungsbild kümmert, so dass keiner ihrer Vorfahren dies tut.

22
Mike Tronic

Wir können Refs auf andere Weise verwenden,

Wir werden ein übergeordnetes Element erstellen, es wird eine <Child/>-Komponente dargestellt. Wie Sie sehen können, muss die Komponente, die gerendert wird, das ref -Attribut hinzufügen und einen Namen dafür angeben.
.__ Die triggerChildAlert-Funktion, die sich in der übergeordneten Klasse befindet, greift auf die refs -Eigenschaft dieses Kontextes zu (wenn die triggerChildAlert-Funktion ausgelöst wird, wird auf die untergeordnete Referenz zugegriffen und sie verfügt über alle Funktionen des untergeordneten Elements. 

class Parent extends React.Component {
    triggerChildAlert(){
        this.refs.child.callChildMethod();
        // to get child parent returned  value-
        // this.value = this.refs.child.callChildMethod();
        // alert('Returned value- '+this.value);
    }

    render() {
        return (
            <div>
                {/* Note that you need to give a value to the ref parameter, in this case child*/}
                <Child ref="child" />
                <button onClick={this.triggerChildAlert}>Click</button>
            </div>
        );
    }
}  

Nun sieht die untergeordnete Komponente, wie zuvor theoretisch entworfen, folgendermaßen aus: 

class Child extends React.Component {
    callChildMethod() {
        alert('Hello World');
        // to return some value
        // return this.state.someValue;
    }

    render() {
        return (
            <h1>Hello</h1>
        );
    }
}

Hier ist der Quellcode-
Hoffnung wird dir helfen!

4
S.Yadav

Wenn Sie dies tun, nur weil Sie möchten, dass das Kind seinen Eltern ein wiederverwendbares Merkmal verleiht, sollten Sie dies stattdessen mit mit render-props tun.

Diese Technik stellt die Struktur tatsächlich auf den Kopf. Die Child umschließt nun das übergeordnete Element, daher habe ich es in AlertTrait umbenannt. Ich habe den Namen Parent für die Kontinuität beibehalten, obwohl er jetzt nicht wirklich ein Elternteil ist.

// Use it like this:

  <AlertTrait renderComponent={Parent}/>


class AlertTrait extends Component {
  // You may need to bind this function, if it is stateful
  doAlert() {
    alert('clicked');
  }
  render() {
    return this.props.renderComponent(this.doAlert);
  }
}

class Parent extends Component {
  render() {
    return (
      <button onClick={this.props.doAlert}>Click</button>
    );
  }
}

In diesem Fall bietet das AlertTrait eine oder mehrere Eigenschaften, die es als Requisiten an die Komponente weitergibt, die es in seiner renderComponent-Prop gegeben hat.

Das übergeordnete Element empfängt doAlert als Requisite und kann es bei Bedarf aufrufen.

(Der Klarheit halber habe ich im obigen Beispiel die Stütze renderComponent genannt. In den oben verlinkten React-Dokumenten heißt es nur render.)

Die Trait-Komponente kann in der Renderfunktion alles rund um das übergeordnete Element rendern, es werden jedoch keine Objekte im übergeordneten Element gerendert. Tatsächlich könnte es Dinge innerhalb des übergeordneten Elements darstellen, wenn es eine andere Eigenschaft (z. B. renderChild) an das übergeordnete Element übergeben hat, die das übergeordnete Element dann während seiner Rendermethode verwenden könnte.

Dies unterscheidet sich ein wenig von dem, was das OP gefordert hat, aber manche Leute könnten hier landen (wie wir), weil sie ein wiederverwendbares Merkmal erstellen wollten und der Meinung waren, dass eine Kindkomponente ein guter Weg ist, dies zu tun.

3
joeytwiddle

Sie können Inheritance Inversion vornehmen (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 umwickeln würden (damit Sie auf ihre Funktionen zugreifen können).

0
szpada87

Ich denke, die grundlegendste Methode zum Aufruf von Methoden besteht darin, eine Anforderung für die untergeordnete Komponente festzulegen. Sobald das untergeordnete Element die Anforderung verarbeitet, ruft es eine Rückrufmethode auf, um die Anforderung zurückzusetzen.

Der Rücksetzmechanismus ist notwendig, um dieselbe Anfrage mehrfach hintereinander senden zu können.

In übergeordneter Komponente

In der Rendermethode des übergeordneten Elements:

const { request } = this.state;
return (<Child request={request} onRequestHandled={()->resetRequest()}/>);

Der Elternteil benötigt zwei Methoden, um mit seinem Kind in zwei Richtungen zu kommunizieren.

sendRequest() {
  const request = { param: "value" };
  this.setState({ request });
}

resetRequest() {
  const request = null;
  this.setState({ request });
}

In der untergeordneten Komponente

Das Kind aktualisiert seinen internen Zustand und kopiert die Anforderung aus den Requisiten.

constructor(props) {
  super(props);
  const { request } = props;
  this.state = { request };
}

static getDerivedStateFromProps(props, state) {
  const { request } = props;
  if (request !== state.request ) return { request };
  return null;
}

Dann bearbeitet er die Anfrage und sendet den Reset an das übergeordnete Element:

componentDidMount() {
  const { request } = this.state;
  // todo handle request.

  const { onRequestHandled } = this.props;
  if (onRequestHandled != null) onRequestHandled();
}
0
bvdb

Sie können dies auf diese Weise leicht erreichen

Schritte-

  1. Erstellen Sie eine boolesche Variable im Status der übergeordneten Klasse. Aktualisieren Sie dies, wenn Sie eine Funktion aufrufen möchten.
  2. Erstellen Sie eine Requisitenvariable und weisen Sie die boolesche Variable zu.
  3. Greifen Sie über die untergeordnete Komponente mit Requisiten auf diese Variable zu, und führen Sie die gewünschte Methode aus, indem Sie eine if-Bedingung angeben.

    class Child extends Component {
       Method=()=>{
       --Your method body--
       }
       render() {
         return (
        //check whether the variable has been updated or not
          if(this.props.updateMethod){
            this.Method();
          }
         )
       }
    }
    
    class Parent extends Component {
    
    constructor(){
      this.state={
       callMethod:false
      }
    
    }
    render() {
       return (
    
         //update state according to your requirement
         this.setState({
            callMethod:true
         }}
         <Child updateMethod={this.state.callMethod}></Child>
        );
       }
    }
    
0
Kusal Kithmal