The most common way to call this.setState()
is to call a custom function that wraps a this.setState()
call. .makeSomeFog()
is an example:
class Example extends React.Component { constructor(props) { super(props); this.state = { weather: 'sunny' }; this.makeSomeFog = this.makeSomeFog.bind(this); } makeSomeFog() { this.setState({ weather: 'foggy' }); } }
Notice how the method makeSomeFog()
contains a call to this.setState()
.
You may have noticed a weird line in there:
this.makeSomeFog = this.makeSomeFog.bind(this);
This line is necessary because makeSomeFog()
‘s body contains the word this
. We’ll talk about it more soon!
Let’s walk through how a function wrapping this.setState()
might work in practice. In the code editor, read Mood.js all the way through.
Here is how a <Mood />
‘s state would be set:
A user triggers an event (in this case a click event, triggered by clicking on a
<button></button>
).The event from Step 1 is being listened for (in this case by the
onClick
attribute on line 20).When this listened-for event occurs, it calls an event handler function (in this case,
this.toggleMood()
, called on line 20 and defined on lines 11-14).Inside of the body of the event handler,
this.setState()
is called (in this case on line 13).The component’s
state
is changed!
Due to the way that event handlers are bound in JavaScript, this.toggleMood()
loses its this
when it is used on line 20. Therefore, the expressions this.state.mood
and this.setState
on lines 12 and 13 won’t mean what they’re supposed to… unless you have already bound the correct this
to this.toggleMood
.
That is why we must bind this.toggleMood
to this
on line 8.
For an in-depth explanation of this kind of binding trickery, begin with the React docs. For the less curious, just know that in React, whenever you define an event handler that uses this
, you need to add this.methodName = this.methodName.bind(this)
to your constructor function.
Look at the statement on line 12. What does that do?
Line 12 declares a const
named newMood
equal to the opposite of this.state.mood
. If this.state.mood
is “good”, then newMood
will be “bad,” and vice versa.
A <Mood />
instance would display “I’m feeling good!” along with a button. Clicking on the button would change the display to “I’m feeling bad!” Clicking again would change back to “I’m feeling good!”, etc. Try to follow the step-by-step walkthrough in Mood.js and see how all of this works.
One final note: you can’t call this.setState()
from inside of the render function! We’ll explain why in the next exercise.
Instructions
In the code editor, select Toggle.js.
Before the render method, give Toggle
a constructor()
method. Toggle
‘s constructor()
method should have one parameter, named props
.
Inside the body of the your constructor method, call super(props)
;
On a new line, still inside the body of your constructor method, set this.state
equal to this object: { color: green }
. Use the example as a guide.
Don’t put green
in quotes! green
should not be a string, it should be a reference to the variable declared on line 4.
Inside of Toggle
‘s render method, give the <div></div>
the following attribute:
style={{background: this.state.color}}
Make sure to include the double curly braces! We’ll explain those in a later lesson.
On line 2, import the ReactDOM
library from react-dom
.
At the bottom of the file, render <Toggle />
using ReactDOM.render()
.
Click Run and see if the background color reflects the state
.
In between constructor()
and render()
, define a new method named changeColor()
.
changeColor()
should set the state’s color
to yellow if it’s currently green, and vice versa.
You just wrote a component class method that called this.setState()
. When you write a component class method that uses this
, then you need to bind that method inside of your constructor function!
Add the following line to the end of constructor()
:
this.changeColor = this.changeColor.bind(this);
In Toggle.js, in the render method, underneath the <h1></h1>
, add this JSX element:
<button> Change color </button>
Now let’s make the button actually work!
Give the <button></button>
an onClick
attribute with a value of {this.changeColor}
.
Hit Run and let the browser refresh. Does clicking on the button change the color?