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);
user1518183
quelle
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 .

Ross Allen
quelle
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 .

Sjoerd
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
Paul O'Shannessy
quelle
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)
Jay
quelle
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();
Jewgen Safronow
quelle
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)
  }
}
Swennemen
quelle
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();
mgalgs
quelle
-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?

Hou Soune
quelle