1. React类组件中的state
state属性是React的组件类(Component)预先定义好的一个私有属性,定义一个ES6支持的class类来继承Component类成为一个类组件(在React16.8.0之前,函数组件是没有状态的)。这个类组件中的state包含了一些随时会改变的数据,跟渲染界面无关的数据没必要定义到state中,可以直接挂到这个类组件的实例this上。
import React, { Component } from 'react'
export default class App extends Component {
constructor() {
super()
this.state = {
count: 1
}
}
render() {
return (
<div>
{this.state.count}
<button onClick={this.click}>add</button>
</div>
)
}
}
2. 修改状态setState
修改状态state时需要注意:
(1) 不要直接修改state。如果直接修改state,组件并不会重新渲染。可以在类组件的构造函数(constructor)中给state赋初值,修改state要用setState(state | updater, callback)。
setState方法接收两个参数。第一个参数是一个对象state或者是带形参的函数updater,修改后的状态与原状态相关联时可以传入updater。第二个参数callback是一个可选回调函数,callback在状态state和dom更新完成时被调用。
componentDidUpdate() {
console.log("钩子函数componentDidUpdate中访问state:"+this.state.count)
}
click = () => {
this.setState((s)=>{return {count: s.count + 1}},()=>{
console.log("setState的第二个参数回调中访问state:"+this.state.count)
})
}
每点击一次按钮add后将state.count的值加一,点击一次按钮后的结果:
(2) setState修改状态更新可能是异步的,会批量推迟更新,在调用setState后直接访问state是还没有更新的状态,在生命周期函componentDidUpdate或者setState的第二个参数的回调函数中访问到的state才是更新完后的状态,而且React出于性能考虑会合并多个setState。
import React, { Component } from 'react'
export default class App extends Component {
constructor() {
super()
this.state = {
count: 1
}
}
render() {
return (
<div>
{this.state.count}
<button onClick={this.click}>add</button>
</div>
)
}
componentDidUpdate() {
console.log("钩子函数componentDidUpdate中访问state:"+this.state.count)
}
click = () => {
this.setState({
count: 2
})
console.log("setState后直接访问state:"+this.state.count)
this.setState({
count: 2
})
this.setState({
count: 2
},()=>{
console.log("setState的第二个参数回调中访问state:"+this.state.count)
})
}
}
每次点击按钮add将状态state.count的值修改为2,点击一次按钮后的结果:
3. React17.0.2中的state
在react18之前,类组件的状态更新setState在setTimeOut、setInterval这样的异步逻辑中执行,react会同步更新状态和dom,在同步逻辑中则会异步更新状态和dom。
首先将react版本回退到v17.0.2:
click = () => {
this.setState({
count: 2
})
console.log("React17.0.2中的同步逻辑中:"+this.state.count)
}
setState在同步逻辑中是异步更新执行结果:
click = () => {
setTimeout(()=>{
this.setState({
count: 2
})
console.log("React17.0.2中的异步逻辑中:"+this.state.count)
},10);
}
setState在异步逻辑中是同步更新执行结果:
4. React18.2.0中的state
在react18之后,类组件的状态更新在同步和异步逻辑中都是异步的。
click = () => {
this.setState({
count: 2
})
console.log("React18.2.0中的同步逻辑中:"+this.state.count)
}
setState在同步逻辑中是异步更新执行结果:
click = () => {
setTimeout(()=>{
this.setState({
count: 2
})
console.log("React18.2.0中的异步逻辑中:"+this.state.count)
},10)
}
setState在异步逻辑中也是异步更新执行结果: