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);
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
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 .
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
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();
À 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)
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)
}
}
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();