5 hours
In the React Intro, we have discussed how React renders HTML.
Now the problem arises: How do we store and change component information we want in the UI? For example, maybe you want a button’s background color to change once it’s been clicked. The solution is to use state
.
javascript class Message extends React.Component { constructor(){ this.state = { message : "message" } } } console.log(this.state.message);
javascript class Message extends React.Component { constructor(){ this.state = { message : "message" } } render(){ console.log(this.state.message); } }
Incorrect
Correct
Incorrect
Define state.
Initialize state inside class constructor.
this.setState
Incorrect way -
Correct way -
The important thing to remember about setState
is that it causes the component to re-render. Well, in introduction to React, we have learnt that React follows a special path called the React cycle. So, when state is updated using setState
, React goes into the React cycle and then the changes are compared to the previous React virtual DOM element and the changes are made accordingly and are reflected in the UI.
Now let us understand the use of state with an example.
We will create an increment/decrement counter which includes click functionality and displaying that value. When we click on the increment button, 1 is added to the value and on clicking the decrement button, 1 is subtracted from the value. Initially, the value will be 0.
That is all which will be displayed on the page. Now we need to implement the functionality when the buttons are clicked.
So, let us create a function which will run when increment button is clicked. To increment the value in the state, we will take the previous value and add 1 to it by using setState function.
Note:- setState is a predefined function in React which is used to update the state. The setState function has two function definitions i.e. it can either take an object as a parameter or a function as a parameter.
For now, let us use the object instance only.
<button onClick="{this.addValue}">Increment</button>
<button onClick="{this.subtractValue}">Decrement</button>
?
) or by using double ampersand(for single value true, &&
).{
this.state.value < 10 && <button onClick={this.addValue}>Increment</button>;
}
{
this.state.value > 0 && (
<button onClick={this.subtractValue}>Decrement</button>
);
}
That’s all. We have completed our first application in React using React state. To see the complete code Codepen.
Note :- Component will re-render itself only when its state is changed by the component itself and also when the props are changed by parent component. If a component changes its own props , then the component will not be re-rendered. Let us understand this with an example.
Say there is a parent component called App
and a Message
child component which displays a certain message. App
component has a property in state called message
with initial value as message
. This state property is passed as prop to Message
component. Message
component has its own state and a property value
which is defined in it. There are 3 buttons :-
App
component which will change its state (message
).Message
component and it will change the state of Message
component(value
).Message
component which will change its own props(message
- passed by App
component).class Message extends React.Component {
constructor() {
super();
this.state = {
value: 'Hello'
};
}
// Function which will change the state of Message Component
changeState = () => {
this.setState({
value: 'World'
});
};
// Function which will change the message prop
changeProp = () => {
this.props.message = 'Change Prop message';
};
render() {
return (
<div>
<button onClick={this.changeState}> Change Message Comp state </button>
<button onClick={this.changeProp}> Change prop by Message Comp </button>
<p>Prop display {this.props.message}</p>{' '}
<p> Value display {this.state.value}</p>
</div>
);
}
}
class App extends React.Component {
constructor() {
//Constructor
super();
this.state = {
message: 'message' // message property defined in state
};
}
// This function will change the state of App Component
changeState = () => {
this.setState({
message: 'New Message'
});
};
render() {
return (
<div>
<button type="button" onClick={this.changeState}>
{' '}
Change App Comp State
</button>
<Message message={this.state.message} />
{/* Message Component - prop passed as message */}
</div>
);
}
}
Now let us click this button in sequence defined -
Change App Comp State
button. We see that the value of message
has been changed to new message
as the state of App
component changes. Here, the component is re-rendered and the value is passed as prop to Message
component and the change is reflected.Change Message Comp state
button. We see that the value
is now world
. Again the component changes its state and so it is re-rendered.Change prop by Message Comp
button. We see that no change happens to the UI.Change Message Comp state
button. We see that the value of message
prop has been changed to Change Prop message
.How did this happen ?
Well, when we clicked on Change prop by Message Comp
button the value of prop got changed. But since, changing its own prop component does not re-render itself, the changes were not displayed. Although the value of prop was changed to Change Prop message, it was not reflected. When we clicked on Change Message Comp state
button, the state got updated and the component was re-rendered, therefore the prop changes were also reflected on the UI.
One more thing to see here is that the prop message
sent by App
component had the value message first and then, it got changed to new message. But now message
prop has value Change Prop message. This shows inconsistency. Therefore components follow the rule of pure functions which state that the props (parameters) received by component should not be updated.
To see the complete code Codepen
For independent practice, let us create a simple game. Say you are a magician having a magic box and 3 random buttons. Out of 3, only 1 button is correct which reveals the text inside the magic box. Children will come to you and choose a button. If the button is correct, any random text which is present inside the box must be displayed and status message should be displayed as you win. If the button chosen is incorrect, then only one message should be displayed as you lose.
UI should contain -