React setState
setState()更新状态的2种写法
- setState(updater, [callback])
updater为返回stateChange对象的函数: (state, props) => stateChange 接收的state和props被保证为最新的
- setState(stateChange, [callback])
stateChange为对象, callback是可选的回调函数, 在状态更新且界面更新后才执行
下面是setstate简单的代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
class Demo extends React.Component {
static defaultProps = {
name: "defaultProps"
}
state = {
count: 1,
}
// count数量加1
test1 = () => {
/* this.setState({
count: this.state.count + 1
}) */
this.setState((state, props) => { console.log(props); return { count: state.count + 1 } }) // 调用函数形式的setState()更新状态
console.log('setState()之后,this.state.count值:', this.state.count) // ?
}
// count数量变为3
test2 = () => {
this.setState({ count: 3 },
) // 调用对象形式的setState()更新状态
console.log('调用对象形式的setState()之后,this.state.count值:', this.state.count)
}
// 带回调的setState()
test3 = () => {
this.setState(
state => ({ count: state.count + 1 }),
() => {// 什么时候执行? 状态数据更新且界面更新后立即执行
console.log('在callback中,this.state.count值:', this.state.count)
}
)
}
render() {
console.log(' render()后,this.state.count值:', this.state.count)
return (
<div>
<h1>Demo组件: {this.state.count}</h1>
<button onClick={this.test1}>调用函数形式的setState()更新状态+1</button>
<button onClick={this.test2}>调用对象形式的setState()更新状态使count变3</button>
<button onClick={this.test3}>'在callback中', this.state.count的值</button>
</div>
)
}
}
export default Demo
上面这段代码简述了this.state的详细用法,在callback中,显然能拿到最新的state的值,callback回调函数应该在render后执行。
根据上述console.log打印出的值,似乎能看出setState是异步执行的,不过其实并不是这样的,我们来看下面的代码。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
class Demo1 extends React.Component {
constructor(props){
super(props)
this.state = {
count: 0,
}
this.button=React.createRef()
}
/*
react生命周期勾子中, setState()是异步更新状态
*/
componentDidMount() {
console.log('setState()之前', this.state.count)
this.setState(state => ({ count: state.count + 1 }))
console.log('setState()之后', this.state.count)
}
/*
react事件监听回调中, setState()是异步更新状态
*/
update1 = () => {
console.log('setState()之前', this.state.count)
this.setState(state => ({ count: state.count + 1 }))
console.log('setState()之后', this.state.count)
}
/*
定时器回调 / 原生事件监听回调 / promise回调
setState()是同步更新状态
*/
update2 = () => {
setTimeout(() => {
console.log('setState()之前', this.state.count)
this.setState(state => ({ count: state.count + 1 }))
console.log('setState()之后', this.state.count)
}, 0);
}
update3 = () => {
this.button.current.onclick = () => {
console.log('setState()之前', this.state.count)
this.setState(state => ({ count: state.count + 1 }))
console.log('setState()之后', this.state.count)
}
}
update4 = () => {
Promise.resolve().then(() => {
console.log('setState()之前', this.state.count)
this.setState(state => ({ count: state.count + 1 }))
console.log('setState()之后', this.state.count)
})
}
render() {
const { count } = this.state
console.log('render()', count)
return (
<div>
<h2>{count}</h2>
<button onClick={this.update1}>react事件中更新</button> ---
<button onClick={this.update2}>定时器事件中更新</button>
<button ref={this.button} onClick={this.update3}>原生事件中更新</button>
<button onClick={this.update4}>promise中更新</button> ---
</div>
)
}
}
export default Demo1
总结 异步执行 在react控制的回调函数中: 生命周期勾子 / react事件监听回调
同步执行 非react控制的异步回调函数中: 定时器回调 / 原生事件监听回调 / promise回调 /...
接着,我们再来看看用函数形式和对象形式的区别,我们用两次调用setState来对比
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
class Demo2 extends React.Component {
constructor(props){
super(props)
this.state = {
count: 0,
}
}
/*
2次调用函数方式的setState()
*/
update1 = () => {
console.log('setState()之前', this.state.count)
this.setState(state => ({ count: state.count + 1 }))
console.log('setState()之后', this.state.count)
console.log('setState()2之前', this.state.count)
this.setState(state => ({ count: state.count + 1 }))
console.log('setState()2之后', this.state.count)
}
/*
2次调用对象方式的setState()
*/
update2 = () => {
console.log('setState()之前', this.state.count)
this.setState({ count: this.state.count + 1 })
console.log('setState()之后', this.state.count)
console.log('setState()2之前', this.state.count)
this.setState({ count: this.state.count + 0 })
console.log('setState()2之后', this.state.count)
}
/*
先对象方式后函数方式的setState()
*/
update3 = () => {
console.log('setState()之前', this.state.count)
this.setState({ count: this.state.count + 1 })
console.log('setState()之后', this.state.count)
console.log('setState2()之前', this.state.count)
this.setState(state => ({ count: state.count + 1 }))
console.log('setState()2之后', this.state.count)
}
/*
先函数方式后对象方式的setState()
*/
update4 = () => {
console.log('setState()之前', this.state.count)
this.setState(state => ({ count: state.count + 1 }))
console.log('setState()之后', this.state.count)
console.log('setState()2之前', this.state.count)
this.setState({ count: this.state.count + 1 })
console.log('setState()2之后', this.state.count)
}
render() {
const { count } = this.state
console.log('render()', count)
return (
<div>
<h2>{count}</h2>
<button onClick={this.update1}>2次调用函数方式的setState()</button>
<button onClick={this.update2}>2次调用对象方式的setState()</button>
<button onClick={this.update3}>先对象方式后函数方式的setState()</button>
<button onClick={this.update4}>先函数方式后对象方式的setState()</button>
</div>
)
}
}
export default Demo2
很明显,
对象方式,合并更新一次状态,只调用最后一次
函数方式,会更新多次状态,但同样render的运行还是一次。
总结:
- 对象方式是函数方式的简写方式
- 如果新状态不依赖于原状态 ===> 使用对象方式 如果新状态依赖于原状态 ===> 使用函数方式
- 如果需要在setState()后获取最新的状态数据, 在第二个callback函数中读取
(完)
0条看法
最新最后最热
等待你的评论