web-dev-qa-db-fra.com

React.js - accès aux méthodes de composant

Pourquoi ne puis-je pas accéder aux méthodes de composant depuis "dehors" dans ReactJS? Pourquoi n'est-ce pas possible et y a-t-il un moyen de le résoudre?

Considérons le 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);
137
user1518183

React fournit une interface pour ce que vous essayez de faire via l’attribut ref . Attribuez à un composant un callback ref. Il sera appelé avec une référence au composant lors de son rendu:

var Parent = React.createClass({
    componentDidMount: function() {
        console.log(this._child.someMethod()); // Prints 'bar'
    },
    render: function() {
        return (
            <div>
                <Child ref={(child) => { this._child = child; }} />
            </div>
        );
    }
});

Mise à jour du 19/09/2016: _ ​​Exemple modifié pour utiliser le rappel de référence plutôt que la référence de chaîne selon les indications fournies par l'attribut ref String docs.

Note: Cela ne fonctionnera que si le composant enfant est déclaré en tant que classe, conformément à la documentation disponible ici: https://facebook.github.io/react/docs/refs-and-the-dom. html # add-a-ref-to-a-class-composant

157
Ross Allen

Si vous souhaitez appeler des fonctions sur des composants extérieurs à React, vous pouvez les appeler à la valeur de retour de renderComponent:

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

La seule façon d'obtenir un handle vers une instance de React Component en dehors de React consiste à stocker la valeur de retour de React.renderComponent. La source .

37
Sjoerd

Sinon, si la méthode sur Child est vraiment statique (pas un produit de props, état), vous pouvez la définir sur statics puis y accéder comme une méthode de classe statique. Par exemple:

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

console.log(Child.someMethod()) // bar
36
Paul O'Shannessy

Depuis React 0.12, l'API est légèrement modifié . Le code valide pour initialiser myChild serait le suivant:

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

À partir de la version 16.3, React.createRef peut être utilisé (utilisez ref.current pour accéder)

var ref = React.createRef()

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

React.renderComponent(parent, document.body)
1
Jay

Vous pourriez faites-le aussi, ne savez pas si c'est un bon plan

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)
  }
}
0
swennemen

Comme mentionné dans certains commentaires, ReactDOM.render ne renvoie plus l'instance de composant. Vous pouvez passer un callback ref lors du rendu de la racine du composant pour obtenir l'instance, comme suit:

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

et:

// Vanilla javascript code
var global_widget_instance;

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

global_widget_instance.myCoolMethod();
0
mgalgs