Setting Initial State
A React component can access dynamic information in two ways: props
and state
Unlike props
, a component's state
is not passed in from the outside. A component decides its own state
.
To make a component have state
, give a component a state
property. The state
property should be declared inside of a constructor method.:
class Example extends React.Component {
constructor(props) { // constructor method
super(props);
this.state = { mood: 'decent' }; // state property
}
render() {
return <div></div>;
}
}
<Example />
this.state
=
{}
This object represents the initial state of any component instance.
constructor()
and super()
are both features of ES6, not unique to React. More on them here and here.
Accessing a Component's state
To read a component's state, use the expression this.state.name-of-property
class TodayImFeeling extends React.Component {
constructor(props) {
super(props);
this.state = { mood: 'decent' };
}
render() {
return (
<h1>
I'm feeling {this.state.mood}!
</h1>
);
}
}
Updating state
with this.setState
A component can do more than just read its own state, it can also change its own state.
this.setState()
Takes two arguments: an _object _that will update the component's state and a callback. (You basically never need the callback)
this.setState({ hungry: true })
this.setState()
takes an object and merges that object with the component's current state.
{
hungry: true,
mood: 'great'
}
Call this.setState
from Another Function
The most common way to call this.setState()
is to call a function that wraps a this.setState()
call.
toggleMood()
is the wrapper function below:
import React from 'react';
import ReactDOM from 'react-dom';
class Mood extends React.Component {
constructor(props) {
super(props);
this.state = { mood: 'good' };
this.toggleMood = this.toggleMood.bind(this);
}
toggleMood() {
const newMood = this.state.mood == 'good' ? 'bad' : 'good';
this.setState({ mood: newMood });
}
render() {
return (
<div>
<h1>I'm feeling {this.state.mood}!</h1>
<button onClick={this.toggleMood}>
Click Me
</button>
</div>
);
}
}
ReactDOM.render(<Mood />, document.getElementById('app'));
Here is how <Mood />
's state would be set:
- A user triggers an
onClick
by clicking a<button>
. - When this listened-for event occurs, it calls an event handler function
this.toggleMood()
- Inside the body of the event handler,
this.setState()
is called - The component's
state
is changed!
.bind()
Due to the way that event handlers are bound in JavaScript , this.toggleMood()
loses its this
when used in <button onClick={this.toggleMood}>
. Therefore, whenever you define an event handler that uses this
, you need to add this.methodName = this.methodName.bind(this)
to your constructor function.
import React from 'react';
import ReactDOM from 'react-dom';
const green = '#39D1B4';
const yellow = '#FFD712';
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { color: green };
this.changeColor = this.changeColor.bind(this);
}
changeColor() {
const newColor = this.state.color == green ? yellow : green;
this.setState({ color: newColor });
}
render() {
return (
<div style={{background:this.state.color}}>
<h1>
<button onClick={this.changeColor}>Change color</button>
</h1>
</div>
);
}
}
ReactDOM.render(<Toggle />, document.getElementById('app'));
this.setState()
Automatically Calls render()
When the <button>
is clicked, it calls changeColor()
which calls this.setState()
which updates this.state.color
.
Since {{background:this.state.color}}
is in render()
, and this.setState()
automatically calls render()
the background is magically rendering without having to re-render <Toggle />
.