In order to execute a function from a child component, you will need to use Refs. React supports a special attribute that you can attach to any component, that's the ref
attribute, it takes a callback function, and you can access the functions of the child component in the parent accessing this.refs.REF_NAME.METHOD_NAME
.
We are going to create a Parent element, it will render a <Child/>
component. As you can see, the component that will be rendered, you need to add the ref
attribute and provide a name for it. Then, the triggerChildAlert
function, located in the parent class will access the refs property of the this context (when the triggerChildAlert function is triggered will access the child reference and it will has all the functions of the child element).
class Parent extends React.Component {
triggerChildAlert(){
this.refs.child.showAlert();
}
render() {
return (
<div>
{/* Note that you need to give a value to the ref parameter, in this case child*/}
<Child ref="child" />
<button onClick={this.triggerChildAlert}>Click</button>
</div>
);
}
}
Now, the child component, as theoretically designed previously, will look like:
class Child extends React.Component {
showAlert() {
alert('Hello World');
}
render() {
return (
<h1>Hello</h1>
);
}
}
The showAlert
method is the only method that will be accesible in this.refs.child
in the parent component.
Example
If you didn't understood well the previous example, you can analyze the following implementation. In this example, we are going to use material-ui and 2 of its components, the drawer and a button. The custom drawer will be located in an extra file Drawer.js:
// Drawer.js
import React from 'react';
import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';
export default class DrawerMain extends React.Component {
constructor(props) {
super(props);
this.state = {open: false};
}
// Shows or hide the Drawer
handleToggle = () => this.setState({open: !this.state.open});
// Closes the drawer
handleClose = () => this.setState({open: false});
render() {
return (
<div>
<Drawer
docked={false}
width={200}
open={this.state.open}
onRequestChange={(open) => this.setState({open})}
>
<MenuItem onTouchTap={this.handleClose}>Menu Item</MenuItem>
<MenuItem onTouchTap={this.handleClose}>Menu Item 2</MenuItem>
</Drawer>
</div>
);
}
}
Nothing special that we need to pay attention, the handleToggle
method is only accesible in the Drawer component, however as we are not going to add any button inside the <Drawer />
component, we need of some way access those methods, otherwise we couldn't use the Drawer. Therefore, in our </Main>
component, we are going to add a simple button that will show the drawer and will access the handleToggle method in the <Drawer />
component:
import React, {Component} from 'react';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import FloatingActionButton from 'material-ui/FloatingActionButton';
import ContentAdd from 'material-ui/svg-icons/image/add-a-photo';
// Import the drawer component previously created as DrawerMain
import DrawerMain from './Drawer';
class Main extends Component {
constructor(props, context) {
super(props, context);
}
handleDrawer = () => {
// Access the handleToggle function of the drawer reference
this.refs.customDrawerReference.handleToggle();
}
render() {
return (
<MuiThemeProvider muiTheme={muiTheme}>
<div>
{/* Add the Drawer and create the "drawer" reference */}
<DrawerMain ref="customDrawerReference"/>
{/* The button that will open the drawer onTouchTap (click or whatever) */}
<FloatingActionButton style={style} onTouchTap={this.handleDrawer}>
<ContentAdd />
</FloatingActionButton>
</div>
</MuiThemeProvider>
);
}
}
export default Main;
If you want more information about the ref attribute, read the official documentation in react here. Happy coding !