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.
Suppose you have two components, a BannerMessage
and Editor
. The BannerMessage
is a component that maintains a single state variable called message
:
1import React from 'react';
2import Editor from './Editor';
3
4export default class BannerMessage extends React.Component {
5 constructor(props) {
6 super(props);
7
8 this.state = {
9 message: ""
10 }
11 }
12
13 updateMessage(message) {
14 this.setState({
15 message: message
16 });
17 }
18
19 render() {
20 return (
21 <div>
22 <h1>
23 {this.state.message}
24 </h1>
25 <hr/>
26 <Editor
27 updateMessage={this.updateMessage.bind(this)}
28 />
29 </div>
30 );
31 }
32}
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:
1import React from 'react';
2
3export default class Editor extends React.Component {
4 constructor(props) {
5 super(props);
6
7 this.state = {
8 message: ""
9 }
10 }
11
12 handleMessageChanged(event) {
13 this.setState({
14 message: event.target.value
15 });
16 }
17
18 render() {
19 return (
20 <div>
21 <input type="text" value={this.state.message} onChange={this.handleMessageChanged.bind(this)} />
22 <button>
23 Save Message
24 </button>
25 </div>
26 );
27 }
28}
The component maintains its own state message
that is updated every time the user modifies the value of its input element.
In Editor
, create a method that will serve as an event handler for the button when it is clicked:
1handleButtonClicked() {
2 this.props.updateMessage(this.state.message);
3}
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
:
1<Editor
2 updateMessage={this.updateMessage.bind(this)}
3/>
Attach the event handler to the button's onClick
event within Editor
:
1<button onClick={this.handleButtonClicked.bind(this)}>
2 Save Message
3</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
).
The final code should look like the following:
1import React from 'react';
2import Editor from './Editor';
3
4export default class BannerMessage extends React.Component {
5 constructor(props) {
6 super(props);
7
8 this.state = {
9 message: ""
10 }
11 }
12
13 updateMessage(message) {
14 this.setState({
15 message: message
16 });
17 }
18
19 render() {
20 return (
21 <div>
22 <h1>
23 {this.state.message}
24 </h1>
25 <hr/>
26 <Editor
27 updateMessage={this.updateMessage.bind(this)}
28 />
29 </div>
30 );
31 }
32}
1import React from 'react';
2
3export default class Editor extends React.Component {
4 constructor(props) {
5 super(props);
6
7 this.state = {
8 message: ""
9 }
10 }
11
12 handleMessageChanged(event) {
13 this.setState({
14 message: event.target.value
15 });
16 }
17
18 handleButtonClicked() {
19 this.props.updateMessage(this.state.message);
20 }
21
22 render() {
23 return (
24 <div>
25 <input type="text" value={this.state.message} onChange={this.handleMessageChanged.bind(this)} />
26 <button onClick={this.handleButtonClicked.bind(this)}>
27 Save Message
28 </button>
29 </div>
30 );
31 }
32}
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
.