Data in React state cannot be changed directly
The code in the example is to directly change (wrong)
1
2
3
4changeWeather(){
const isHot=this.state.isHot
this.state.Hot=!isHot //Error!
console.log(this.state.isHot)}The immediate consequence of the change is that the console.log output can toggle between true and false, but the page is not re-rendered. Here you can check the status from inspect => Components, and find that isHot in the status is always the initial value.
setState()
The state state cannot be changed directly, it needs to be changed with the help of a built-in API:
setState()
.setState()
is an asynchronous update.setState()
is available in the React.Components prototype through the inheritance chain. An object is to be written insetState()
, which is the same as state.1
2
3
4changeWeather(){
const isHot=this.state.isHot
this.setState({isHot : ! isHot})
}At this time, the state in inspect=>Components will switch.
The state update action of
setState()
is merged rather than replacedWhen the state is updated, the object in
setState()
will not replace the object in the state as a whole, but only modify the part with the same name.
Times of code executions in class components
The constructor
constructor(props)
is only executed once, the time ReactDOM.render is called when the instance is created.render is called 1+n times. 1 is the time it was initialized, and n is the number of state updates.
changeWeather()
: It is called several times when the click event is triggered several times. setState is inchangeWeather()
.Therefore, React will re-call render once whenever the state is modified via setState. Components are also known as state machines.
Shorthand for state and function
The this in
constructor(props)
andrender()
in the class component points to the class component instance. Because the this in the constructor itself is the instance object of the class, and the this ofrender()
is also the instance object because react creates an instance of the class whenReactDOM.render(<component tag/>...)
is executed. And it is called byinstance.render()
.There is a problem with the this pointer in the custom function, because the custom function is not called through
instance.custom function
, but called through event callbacks (custom functions are almost all called through event callbacks).
Code before simplification
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Weather extends React.Component{
constructor(props){
super(props)
this.state = {isHot:false,wind:'breeze'}
this.changeWeather = this.changeWeather.bind(this) //***
}
render(){
const {isHot,wind} = this.state
return <h1>onClick={this.changeWeather}Today's weather {isHost?'hot':'cool'},{wind}</h1>
}
changeWeather(){
const isHot = this.state.isHot
this.setState({isHot:!isHot})
}
}
Simplified way
Assignment statements can be written directly in the class, such as
a=1
, instead ofthis.property name=fixed value
written in the constructor.This code is to add an attribute to the instance object of the class. If the initial value of this property is passed in from outside, it must be written in the constructor. Therefore, state initialization can be written outside the constructor.
1
state = {isHot: false, wind: "breeze"}
this.changeWeather = this.changeWeather.bind (this)
This statement can be omitted.The purpose of this statement is to change the point of this and copy the changeWeather method on the class prototype object to the instance attribute changeWeather. After being omitted, the changeWeather method does not exist on the function prototype object, but only the instance attribute has changeWeather. And the value of this property is an anonymous function.
Note that it is an error to omit the method
changeWeather=function(){}
. This is because it just changed the changeWeather to another place, and it still reports an error after clicking (because there is no.bind(this)
to change the direction). So the correct way is arrow functions.
The arrow function does not have its own this. When using this in the arrow function, it will find the this of the outer function of the arrow function to use. Therefore, this in the arrow function is the instance object of the component.
1
2
3
4changeWeather = () => {
const isHot = this.state.isHot
this.setState({isHot:!isHot})
}
When writing a custom method in a class component in the future, it must be written in the form of an assignment statement + an arrow function. It is impossible not to write an assignment statement, and a syntax error will be reported. Because if you don’t write assignment, you are putting the function on the class prototype. There is no syntax that can put the arrow function on the class prototype.
1
changeWeather() => {} //Wrong way of writing
abbreviated code
1
2
3
4
5
6
7
8
9
10
11
12
13class Weather extends React.Component{
state = {isHot:false,wind:'breeze'}
changeWeather = () => {
const isHot = this.state.isHot
this.setState({isHot:!isHot})
}
render(){
const {isHot,wind} = this.state
return <h1>onClick={this.changeWeather}Today's weather {isHost?'hot':'cool'},{wind}</h1>
}
}