Unlike Vue, React's settings are asynchronous.
13. setState is an asynchronous behavior
setState()
This is an asynchronous operation, such as:
class HelloWord extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
this.clickCountAsync = this.clickCountAsync.bind(this)
}
// Render function, this points to the instance itself
render() {
return <div>
<button onClick={this.clickCountAsync}>Asynchronous increasecount</button>
</div>
}
clickCountAsync() {
console.log('[Asynchronism setState Before, count Value:', this.state.count)
this.setState({
count: this.state.count + 1
})
console.log('[Asynchronism setState After that, count Value:', this.state.count)
}
}
It will be found that the output value of the two log statements is the same.
The reason is that React merges multiple setState s and updates them uniformly.
Then how to get the updated data, the answer is through the callback function;
Notes
class HelloWord extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
anotherCount: 0
}
this.clickCountAsync = this.clickCountAsync.bind(this)
this.clickCountSync = this.clickCountSync.bind(this)
}
// Render function, this points to the instance itself
render() {
return <div>
<button onClick={this.clickCountAsync}>Asynchronous increasecount</button>
<br/>
<button onClick={this.clickCountSync}>increasecount,And synchronously update the value of counter 2 equal to that of asynchronously increasedcount</button>
<br/>
//Counter 2:{this.state.anotherCount}
</div>
}
clickCountAsync() {
console.log('[Asynchronism setState Before, count Value:', this.state.count)
this.setState({
count: this.state.count + 1
})
console.log('[Asynchronism setState After that, count Value:', this.state.count)
}
clickCountSync() {
// Update the value of state.count through setState
this.clickCountAsync()
// 1. Here is the value before the update.
console.log('[Synchronization] setState Before, count Value:', this.state.count)
this.setState((prevState, props) => {
// 3. The callback function here is executed after updating (i.e.
console.log(prevState, props)
// The return value is like setting the parameters of setState
return {
anotherCount: prevState.count
}
})
// 2. Here is also the pre-update value.
console.log('[Synchronization] setState After that, count Value:', this.state.count)
}
}
Of course, there is another problem, that is, if I call a method, modify the A variable separately, and then call a method to modify the B variable, and the B variable depends on the modified value of the A variable (this is the scenario above);
But if I need to call a third method to modify the C variable, and the value of C depends on the value of B. So that's a problem.
As a result of:
- There are no computed/watch computational attributes like Vue in React. If implementation is required, additional libraries (watch.js/Rx.js/mobx) may need to be introduced.
- The setState itself is asynchronous, and the callback function takes the changed value asynchronously. Therefore, in the case of complex scenarios, it is difficult to determine which setState callback function will be executed first.
Solution:
- One is to introduce additional libraries, which imitate Vue.js.
- Consider using the life cycle function componentWillUpdate(nextProps, nextState) to add the modification logic of dependent variables to this function. The following code can solve some scenarios.
componentWillUpdate(nextProps, nextState) {
nextState.anotherCount *= 2
console.log(nextProps, nextState)
}