State is the data that a component maintains. Different from props, state can change its value.
state
is stored in a JavaScript object.
To introduce state to a component, that component must be a class-based component.
Firstly, we need to add a constructor() method.
constructor()
is a specific Javascript method that sets up the initial state of the component.
Class components should always call the base constructor with props
.
Inside the constructor, we must call super()
and pass in the props
.
import React, {Component} from "react"
class App extends Component {
constructor(props) {
super(props)
}
render() {
return (
// Code here
)
}
}
export default App
After calling the super(props), we can set up our inital state.
To add state to a component, we use this.state
. this.state
is an object.
import React, {Component} from "react"
class App extends Component {
constructor(props) {
super(props)
this.state = {
name: "Jane",
age: 18
}
}
render() {
return (
<div>
<h1>{this.state.name}</h1>
<h3>{this.state.age} years old</h3>
</div>
)
}
}
export default App
To read a component’s state, use the expression this.state.name-of-property
. The above component class reads a property in its state from inside of its render function.
For example, the following App is expected to increase the count by 1 point from 0.
onClick
to the button that runs the method handleClick
.import React from "react"
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
handleClick() {
}
render() {
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={this.handleClick}}>Change!</button>
</div>
)
}
}
export default App
To change the state of a component, we use the method this.setState()
that comes from the parent Class React.Component
.
setState()
will provide a new version of state and take an object literal.
Example
handleClick() {
this.setState({ count: 1 })
}
If we’re changing the state based on the old state, we need to give setState
a function, not an object.
This function takes prevState
as a parameter and return an object that is the new state.
handleClick() {
this.setState(prevState => {
return {
count: prevState.count + 1
}
})
}
Everytime we create a class method using setState, we need to bind this method to our own Class inside the constructor()
.
constructor(props) {
super(props)
this.state = {
count: 0
}
this.handleClick = this.handleClick.bind(this)
}
Our final App.js file will become
import React from "react"
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState(prevState => {
return {
count: prevState.count + 1
}
})
}
render() {
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={this.handleClick}>Change!</button>
</div>
)
}
}
export default App
State is read only so you should not try to manually change the values of the state attributes.
If the state needs to be updated, the setState() method is the only way to change the state.
For example, don’t do this:
//incorrect, state should not be mutated directly
this.state.count = 1