Call a React component method from outside
Solution 1:
There are two ways to access an inner function. One, instance-level, like you want, another, static level.
Instance
You need to call the function on the return from React.render
. See below.
Static
Take a look at ReactJS Statics. Note, however, that a static function cannot access instance-level data, so this
would be undefined
.
var onButtonClick = function () {
//call alertMessage method from the reference of a React Element!
HelloRendered.alertMessage();
//call static alertMessage method from the reference of a React Class!
Hello.alertMessage();
console.log("clicked!");
}
var Hello = React.createClass({
displayName: 'Hello',
statics: {
alertMessage: function () {
alert('static message');
}
},
alertMessage: function () {
alert(this.props.name);
},
render: function () {
return React.createElement("div", null, "Hello ", this.props.name);
}
});
var HelloElement = React.createElement(Hello, {
name: "World"
});
var HelloRendered = React.render(HelloElement, document.getElementById('container'));
Then do HelloRendered.alertMessage()
.
Solution 2:
You can do like
import React from 'react';
class Header extends React.Component{
constructor(){
super();
window.helloComponent = this;
}
alertMessage(){
console.log("Called from outside");
}
render(){
return (
<AppBar style={{background:'#000'}}>
Hello
</AppBar>
)
}
}
export default Header;
Now from outside of this component you can called like this below
window.helloComponent.alertMessage();
Solution 3:
I've done something like this:
class Cow extends React.Component {
constructor (props) {
super(props);
this.state = {text: 'hello'};
}
componentDidMount () {
if (this.props.onMounted) {
this.props.onMounted({
say: text => this.say(text)
});
}
}
render () {
return (
<pre>
___________________
< {this.state.text} >
-------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
</pre>
);
}
say (text) {
this.setState({text: text});
}
}
And then somewhere else:
class Pasture extends React.Component {
render () {
return (
<div>
<Cow onMounted={callbacks => this.cowMounted(callbacks)} />
<button onClick={() => this.changeCow()} />
</div>
);
}
cowMounted (callbacks) {
this.cowCallbacks = callbacks;
}
changeCow () {
this.cowCallbacks.say('moo');
}
}
I haven't tested this exact code, but this is along the lines of what I did in a project of mine and it works nicely :). Of course this is a bad example, you should just use props for this, but in my case the sub-component did an API call which I wanted to keep inside that component. In such a case this is a nice solution.
Solution 4:
1. With React hooks - useImperativeHandle + useRef
const MyComponent = ({myRef}) => {
const handleClick = () => alert('hello world')
useImperativeHandle(myRef, () => ({
handleClick
}), [/* dependencies (if any) */])
return (<button onClick={handleClick}>Original Button</button>)
}
MyComponent.defaultProps = {
myRef: {current: {}}
}
const MyParentComponent = () => {
const myRef = React.useRef({})
return (
<>
<MyComponent
myRef={myRef}
/>
<button onClick={myRef.current.handleClick}>
Additional Button
</button>
</>
)
}
2. With only React hook - useRef
const MyComponent = ({myRef}) => {
const handleClick = () => alert('hello world')
myRef.current.handleClick = handleClick
return (<button onClick={handleClick}>Original Button</button>)
}
MyComponent.defaultProps = {
myRef: {current: {}}
}
const MyParentComponent = () => {
const myRef = React.useRef({})
return (
<>
<MyComponent
myRef={myRef}
/>
<button onClick={myRef.current.handleClick}>
Additional Button
</button>
</>
)
}
Good Luck...