This guide will analyze the primary role of props
in a React.js component, how it is different from state
, and when to use it over state
. This will be done by seeing how props
values are changed within a component as well as how they can be used to update the state
of an external component.
Developers sometimes interchange props
and state
as both can be accessed via the instance of a component and hold data. However, if a component needs to maintain data independent of external components calling it, then state
should be used. If a component needs to render data and invoke functions from another component, those data should be passed through props
.
Suppose that you have two components, Display
and Controls
. Display
will maintain all display information of the application. For now, it will be a simple message
maintained within the state
of Display
. To update the message
of Display
, you will have to invoke its method, updateMessage(message)
.
Create a component Display
which initially looks like this:
1import React from 'react';
2
3export default class Display extends React.Component {
4 constructor(props) {
5 super(props);
6
7 this.state = {
8 message: ""
9 }
10 }
11
12 updateMessage(message) {
13 this.setState({
14 message: message
15 });
16 }
17
18 render() {
19 return (
20 <div>
21 {this.state.message}
22 </div>
23 );
24 }
25}
Notice that all updateMessage(message)
is doing is updating the message
within Display
's state
by invoking setState()
.
Next, create a Controls
component that will contain an input
element. Controls
will be a stateless component—that is, you will not be maintaining any state
values within it. Instead, it will make use of values in props
to be rendered within it.
Create a Controls
component that looks like the following:
1import React from 'react';
2
3export default class Controls extends React.Component {
4 constructor(props) {
5 super(props);
6
7 this.state = {}
8 }
9
10 render() {
11 <div>
12 <input
13 type="text"
14 />
15 Message: {this.props.message}
16 </div>
17 }
18}
Notice that in Controls
's constructor, props
is passed. This means that props
as a set of values are always passed to a component by another component. In this case, that includes values coming from Display
towards Controls
. Within the constructor, a React.js component calls super(props)
to store the passed props
as a property of the component (since everything eventually extends React.Component
, every component has the props
member within it).
Now, in the following line within Controls
's render you have:
1Message: {this.props.message}
This allows this component to display the values of props
that were passed to it—in this case, the message
.
How then can you update message
within Display
? The trick is to update the state of the component calling Display
. To do so, you should be able to invoke Display
's updateMessage(message)
method from Controls
by passing it to props
as well. You have to first invoke Controls
within Display
and pass message
as well as updateMessage
to its props by a set of key value pairs. Import it first at the top part of Display
:
1import Controls from "./Controls";
This assumes that Controls.js
is within the same directory as Display.js
.
Next, display Controls
within Display
's render()
:
1render() {
2 return (
3 <div>
4 {this.state.message}
5 <hr/>
6 <Controls
7 message={this.state.message}
8 updateMessage={this.updateMessage.bind(this)}
9 />
10 </div>
11 );
12}
Notice how message
and updateMessage
become keys that Controls
assigned a value and a method, just like passing values of attributes in an HTML element.
Next, the value of the input
element of Controls
should be bound to the props.message
.
1<input
2 type="text"
3 value={this.props.message}
4/>
This means that if props.message
is updated, the value will displayed within input
. But the only way to update
the props
of Controls
if it is passed by the calling component, Display
.
Next, create a method within Controls
called updateMessage(event)
that will be bound to the onChange
attribute of the input
element.
1updateMessage(event) {
2 this.props.updateMessage(event.target.value);
3}
Notice that it accepts event
, which contains target
, which is a reference to the input
element it is bound to. The target
's value
will then be the value that the user put in. You pass this value to the updateMessage
invoked from props
, which is currently a reference to the updateMessage
of the calling component Display
. Update Controls
's input
element to hook in updateMessage
:
1<input
2 type="text"
3 value={this.props.message}
4 onChange={this.updateMessage.bind(this)}
5/>
Your final code should look like the following:
1import React from 'react';
2import Controls from './Controls';
3
4export default class Display 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 {this.state.message}
23 <hr/>
24 <Controls
25 message={this.state.message}
26 updateMessage={this.updateMessage.bind(this)}
27 />
28 </div>
29 );
30 }
31}
1import React from 'react';
2
3export default class Controls extends React.Component {
4 constructor(props) {
5 super(props);
6
7 this.state = {}
8 }
9
10 updateMessage(event) {
11 this.props.updateMessage(event.target.value);
12 }
13
14 render() {
15 return (
16 <div>
17 <input
18 type="text"
19 value={this.props.message}
20 onChange={this.updateMessage.bind(this)}
21 />
22 </div>
23 );
24 }
25}
As the user enters values in the input
element, updateMessage
of Controls
will be triggered, which in turn calls updateMessage
of Display
. Since the logic of updateMessage
of Display
updates its state, it forces a call to render()
, which in turn passes the updated message
back to Controls
via props
, which in turn is bound to Controls
's input
's value.
props
are different from state
because props
values are passed to a component whereas state
values are initialized within a component. A component can be stateless and only use the props
values passed to it. These values can either contain references to a calling component's state
values or references to a calling component's method. props
containing a method can invoke that method from the calling component. If the state
of a calling component's Display
method is updated, the component that is called Controls
will receive the updated values, thus updating its props
.