Invoking External Component Methods in React.js
In this guide, we'll take a look at how to use props as a means of passing as well as invoking methods of external components.
Oct 10, 2020 • 5 Minute Read
Introduction
React.js components can get complex as your app grows. In most cases, you will have nested components (components that are invoked by other components). These nested components may contain actions that force a state change in the parent component by invoking a method in the parent component. In this guide, we'll take a look at how to use props as a means of passing as well as invoking methods of external components.
Setup
Suppose you have two components, a BannerMessage and Editor. The BannerMessage is a component that maintains a single state variable called message:
import React from 'react';
import Editor from './Editor';
export default class BannerMessage extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ""
}
}
updateMessage(message) {
this.setState({
message: message
});
}
render() {
return (
<div>
<h1>
{this.state.message}
</h1>
<hr/>
<Editor
updateMessage={this.updateMessage.bind(this)}
/>
</div>
);
}
}
Notice that it contains a method called updateMessage that accepts a message value that is updated to the state message of the component. In the render() method, Editor is mounted together with the attribute updateMessage, whose value is this.updateMessage.bind(this). Calling .bind(this) will allow the retention of this pointing to the instance of the BannerMessage component, even if it is passed to Editor.
Editor, on the other hand, looks like the following:
import React from 'react';
export default class Editor extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ""
}
}
handleMessageChanged(event) {
this.setState({
message: event.target.value
});
}
render() {
return (
<div>
<input type="text" value={this.state.message} onChange={this.handleMessageChanged.bind(this)} />
<button>
Save Message
</button>
</div>
);
}
}
The component maintains its own state message that is updated every time the user modifies the value of its input element.
Invoking the External Component's Method
In Editor, create a method that will serve as an event handler for the button when it is clicked:
handleButtonClicked() {
this.props.updateMessage(this.state.message);
}
Notice that the code can invoke the props of the component, which in turn will call updateMessage and pass the value of Editor's message within its state. The call to updateMessage in this context is the one passed by BannerMessage:
<Editor
updateMessage={this.updateMessage.bind(this)}
/>
Attach the event handler to the button's onClick event within Editor:
<button onClick={this.handleButtonClicked.bind(this)}>
Save Message
</button>
When the button is clicked, it will call updateMessage from the component's props, which is a reference to the updateMessage of the parent that passed it (BannerMessage).
Overall Code
The final code should look like the following:
import React from 'react';
import Editor from './Editor';
export default class BannerMessage extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ""
}
}
updateMessage(message) {
this.setState({
message: message
});
}
render() {
return (
<div>
<h1>
{this.state.message}
</h1>
<hr/>
<Editor
updateMessage={this.updateMessage.bind(this)}
/>
</div>
);
}
}
Editor
import React from 'react';
export default class Editor extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ""
}
}
handleMessageChanged(event) {
this.setState({
message: event.target.value
});
}
handleButtonClicked() {
this.props.updateMessage(this.state.message);
}
render() {
return (
<div>
<input type="text" value={this.state.message} onChange={this.handleMessageChanged.bind(this)} />
<button onClick={this.handleButtonClicked.bind(this)}>
Save Message
</button>
</div>
);
}
}
Conclusion
props is a special member of a React.js component that holds values that are passed upon calling a component from another component. The props's keys are declared like HTML attributes, which eventually become references accessible within the component that was called. One such application is passing a reference to the method of the calling component in order to be invoked by the child component, thus triggering the parent's logic. This will allow component-to-component communication while maintaining state independence for each component. For practice, instead of the onClick event, try to see if you can hook the calling of BannerMessage's updateMessage from Editor's onChange event handler. This way, the user doesn't have to click the button in order for Editor to communicate with BannerMessage.