Reputation: 4771
Why can’t I access the component methods from “outside” in ReactJS? Why is it not possible and is there any way to solve it?
Consider the 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);
Upvotes: 220
Views: 214326
Reputation: 1791
As of React 16.3 React.createRef
can be used, (use ref.current
to access)
var ref = React.createRef()
var parent = (
<div>
<Child ref={ref} />
<button onClick={e=>console.log(ref.current)}
</div>
);
React.renderComponent(parent, document.body)
Upvotes: 10
Reputation: 187
Another way so easy:
function outside:
function funx(functionEvents, params) {
console.log("events of funx function: ", functionEvents);
console.log("this of component: ", this);
console.log("params: ", params);
thisFunction.persist();
}
Bind it:
constructor(props) {
super(props);
this.state = {};
this.funxBinded = funx.bind(this);
}
}
Please see complete tutorial here: How to use "this" of a React Component from outside?
Upvotes: -1
Reputation: 44880
React provides an interface for what you are trying to do via the ref
attribute. Assign a component a ref
, and its current
attribute will be your custom component:
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>
);
}
}
Note: This will only work if the child component is declared as a class, as per documentation found here: https://facebook.github.io/react/docs/refs-and-the-dom.html#adding-a-ref-to-a-class-component
Update 2019-04-01: Changed example to use a class and createRef
per latest React docs.
Update 2016-09-19: Changed example to use ref callback per guidance from the ref
String attribute docs.
Upvotes: 223
Reputation: 16749
As mentioned in some of the comments, ReactDOM.render
no longer returns the component instance. You can pass a ref
callback in when rendering the root of the component to get the instance, like so:
// React code (jsx)
function MyWidget(el, refCb) {
ReactDOM.render(<MyComponent ref={refCb} />, el);
}
export default MyWidget;
and:
// vanilla javascript code
var global_widget_instance;
MyApp.MyWidget(document.getElementById('my_container'), function(widget) {
global_widget_instance = widget;
});
global_widget_instance.myCoolMethod();
Upvotes: 2
Reputation: 955
You could also do it like this, not sure if it's a good plan :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)
}
}
Upvotes: 2
Reputation: 4033
Since React 0.12 the API is slightly changed. The valid code to initialize myChild would be the following:
var Child = React.createClass({…});
var myChild = React.render(React.createElement(Child, {}), mountNode);
myChild.someMethod();
Upvotes: 4
Reputation: 75588
If you want to call functions on components from outside React, you can call them on the return value of renderComponent:
var Child = React.createClass({…});
var myChild = React.renderComponent(Child);
myChild.someMethod();
The only way to get a handle to a React Component instance outside of React is by storing the return value of React.renderComponent. Source.
Upvotes: 41
Reputation: 2498
Alternatively, if the method on Child is truly static (not a product of current props, state) you can define it on statics
and then access it as you would a static class method. For example:
var Child = React.createClass({
statics: {
someMethod: function() {
return 'bar';
}
},
// ...
});
console.log(Child.someMethod()) // bar
Upvotes: 38