Wie kann ich in ReactJS von außen auf Komponentenmethoden zugreifen?


182

Warum kann ich in ReactJS nicht von außen auf die Komponentenmethoden zugreifen? Warum ist es nicht möglich und gibt es eine Möglichkeit, es zu lösen?

Betrachten Sie den Code:

var Parent = React.createClass({
    render: function() {
        var child = <Child />;
        return (
            <div>
                {child.someMethod()} // expect "bar", got a "not a function" error.
            </div>
        );
    }
});

var Child = React.createClass({
    render: function() {
        return (
            <div>
                foo
            </div>
        );
    },
    someMethod: function() {
        return 'bar';
    }
});

React.renderComponent(<Parent />, document.body);

Vielleicht brauchst du Pubsub?
Slideshowp2

Antworten:


203

React bietet eine Schnittstelle für das, was Sie über das refAttribut tun möchten . Weisen Sie eine Komponente a zu ref, und ihr currentAttribut ist Ihre benutzerdefinierte Komponente:

class Parent extends React.Class {
    constructor(props) {
        this._child = React.createRef();
    }

    componentDidMount() {
        console.log(this._child.current.someMethod()); // Prints 'bar'
    }

    render() {
        return (
            <div>
                <Child ref={this._child} />
            </div>
        );
    }
}

Hinweis : Dies funktioniert nur, wenn die untergeordnete Komponente gemäß der hier aufgeführten Dokumentation als Klasse deklariert ist: https://facebook.github.io/react/docs/refs-and-the-dom.html#adding-a- Ref-to-a-Class-Komponente

Update 2019-04-01: Das Beispiel wurde geändert, um eine Klasse und die createRefneuesten React-Dokumente zu verwenden.

Update 19.09.2016: Das Beispiel wurde geändert, um den Ref-Rückruf gemäß Anleitung aus den refString-Attributdokumenten zu verwenden .


Die einzige Möglichkeit, zwischen zwei untergeordneten Komponenten zu kommunizieren, besteht darin, sowohl Refs zu haben als auch eine Proxy-Methode für das gemeinsame übergeordnete Element zu durchlaufen.
elQueFaltaba

15
React fördert datengesteuerte Komponenten. Lassen Sie ein Kind einen Rückruf aufrufen, der Daten in seinem Vorfahren ändert, und wenn sich diese Daten ändern, wird das andere Kind neu propsund wird entsprechend neu gerendert.
Ross Allen

@ RossAllen, haha ​​ja, in diesem Fall hättest du auch das Semikolon entfernen müssen.
HussienK

@HussienK Ich bevorzuge die Verwendung eines Blocks, wenn die Funktion keinen Rückgabewert haben sollte, sodass die Absicht für den nächsten Entwickler, der den Code liest, offensichtlich ist. Wenn Sie {(child) => this._child = child}dies ändern, wird eine Funktion erstellt, die immer zurückgegeben wird true, aber dieser Wert wird vom React- refAttribut nicht verwendet .
Ross Allen

39

Wenn Sie Funktionen für Komponenten von außerhalb von React aufrufen möchten, können Sie sie für den Rückgabewert von renderComponent aufrufen:

var Child = React.createClass({…});
var myChild = React.renderComponent(Child);
myChild.someMethod();

Die einzige Möglichkeit, ein Handle für eine React Component-Instanz außerhalb von React zu erhalten, besteht darin, den Rückgabewert von React.renderComponent zu speichern. Quelle .


1
eigentlich funktioniert es für react16. Die Rendermethode ReactDOM gibt einen Verweis auf die Komponente zurück (oder gibt null für zustandslose Komponenten zurück).
Vlad Povalii

37

Wenn die Methode für Child wirklich statisch ist (kein Produkt der aktuellen Requisiten, Status), können Sie sie alternativ definieren staticsund dann wie eine statische Klassenmethode darauf zugreifen. Beispielsweise:

var Child = React.createClass({
  statics: {
    someMethod: function() {
      return 'bar';
    }
  },
  // ...
});

console.log(Child.someMethod()) // bar

1
Quelle dafür ist hier .
Tirdadc

7

Ab React 16.3 React.createRefkann verwendet werden ( ref.currentzum Zugriff verwenden)

var ref = React.createRef()

var parent = <div><Child ref={ref} /> <button onClick={e=>console.log(ref.current)}</div>

React.renderComponent(parent, document.body)

4

Seit React 0.12 wurde die API geringfügig geändert . Der gültige Code zum Initialisieren von myChild lautet wie folgt:

var Child = React.createClass({…});
var myChild = React.render(React.createElement(Child, {}), mountNode);
myChild.someMethod();

1

Sie könnten es auch so machen, nicht sicher, ob es ein guter Plan ist: D.

class Parent extends Component {
  handleClick() {
    if (this._getAlert !== null) {
      this._getAlert()
    }
  }

  render() {
    return (
      <div>
        <Child>
        {(getAlert, childScope) => (
          <span> {!this._getAlert ? this._getAlert = getAlert.bind(childScope) : null}</span>
        )}
        </Child>
        <button onClick={() => this.handleClick()}> Click me</button>
      </div>
      );
    }
  }

class Child extends Component {
  constructor() {
    super();
    this.state = { count: 0 }
  }

  getAlert() {
    alert(`Child function called state: ${this.state.count}`);
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return this.props.children(this.getAlert, this)
  }
}

1

Wie in einigen Kommentaren erwähnt, wird ReactDOM.renderdie Komponenteninstanz nicht mehr zurückgegeben. Sie können einen refRückruf übergeben, wenn Sie das Stammverzeichnis der Komponente rendern, um die Instanz abzurufen:

// React code (jsx)
function MyWidget(el, refCb) {
    ReactDOM.render(<MyComponent ref={refCb} />, el);
}
export default MyWidget;

und:

// vanilla javascript code
var global_widget_instance;

MyApp.MyWidget(document.getElementById('my_container'), function(widget) {
    global_widget_instance = widget;
});

global_widget_instance.myCoolMethod();

-1

Ein anderer Weg so einfach:

Funktion außerhalb:

function funx(functionEvents, params) {
  console.log("events of funx function: ", functionEvents);
  console.log("this of component: ", this);
  console.log("params: ", params);
  thisFunction.persist();
}

Binde es:

constructor(props) {
   super(props);
    this.state = {};
    this.funxBinded = funx.bind(this);
  }
}

Das vollständige Tutorial finden Sie hier: Wie kann man "dies" einer Reaktionskomponente von außen verwenden?

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.