一、setState的基本使用
import React, { Component } from 'react'
export default class index extends Component {
state = { count: 0 }
/**
* 如果不依赖原来的值,建议使用对象方式调用setState
*/
incrementByObject = () => {
this.setState({ count: 5 }, () => {
/**
* 这个方法没有参数,但是可以在这里获取更新之后state的值。
* callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
*/
console.log('incrementByObject', this.state.count)
})
}
/**
* 如果依赖原来的值,建议使用方法方式调用setState
*/
incrementByFunction = () => {
this.setState(state => {
return { count: state.count + 1 }
}, () => {
/**
* 这个方法没有参数,但是可以在这里获取更新之后state的值。
* callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
*/
console.log('incrementByFunction', this.state.count)
})
}
render() {
const { count } = this.state
console.log('render', count)
return (
<div>
<h2>当前值是:{this.state.count}</h2>
<button onClick={this.incrementByObject}>点击我+1==ByObject</button>
<button onClick={this.incrementByFunction}>点击我+1==ByFunction</button>
</div>
)
}
}
二、setState异步调用的方式
import React, { Component } from 'react'
export default class index extends Component {
state = { count: 0 }
/**
* 1.如果不依赖原来的值,建议使用对象方式调用setState
* 2.console.log('incrementByObject之前', this.state.count)
* 和console.log('incrementByObject之后', this.state.count)
* 两句代码是在render方法和this.setState方法回调之前执行。不是
* 顺序执行的。所以是异步
*/
incrementByObject = () => {
console.log('incrementByObject之前', this.state.count)
this.setState({ count: 5 }, () => {
/**
* 这个方法没有参数,但是可以在这里获取更新之后state的值。
* callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
*/
console.log('incrementByObject', this.state.count)
})
console.log('incrementByObject之后', this.state.count)
}
/**
* 1.如果依赖原来的值,建议使用方法方式调用setState
* 2.console.log('incrementByFunction之前', this.state.count)
* 和console.log('incrementByFunction之后', this.state.count)
* 两句代码是在render方法和this.setState方法回调之前执行。不是
* 顺序执行的。所以是异步
*/
incrementByFunction = () => {
console.log('incrementByFunction之前', this.state.count)
this.setState(state => {
return { count: state.count + 1 }
}, () => {
/**
* 这个方法没有参数,但是可以在这里获取更新之后state的值。
* callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
*/
console.log('incrementByFunction', this.state.count)
})
console.log('incrementByFunction之后', this.state.count)
}
/**
* 1.console.log('componentDidMount之前', this.state.count)
* 和console.log('componentDidMount之后', this.state.count)
* 两句代码是在render方法和this.setState方法回调之前执行。不是
* 顺序执行的。所以是异步
*/
componentDidMount() {
console.log('componentDidMount之前', this.state.count)
this.setState({ count: 10 }, () => {
/**
* 这个方法没有参数,但是可以在这里获取更新之后state的值。
* callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
*/
console.log('componentDidMount', this.state.count)
})
console.log('componentDidMount之后', this.state.count)
}
render() {
const { count } = this.state
console.log('render', count)
return (
<div>
<h2>当前值是:{this.state.count}</h2>
<button onClick={this.incrementByObject}>点击我+1==ByObject</button>
<button onClick={this.incrementByFunction}>点击我+1==ByFunction</button>
</div>
)
}
}
三、setState同步调用的方式
import React, { Component } from 'react'
/**
* setTimeout/Promise/dom绑定事件方式阻碍了react的事务,
* 所以影响了this.setState方法的异步调用
*/
export default class index extends Component {
state = { count: 0 }
/**
* 1.如果不依赖原来的值,建议使用对象方式调用setState
* 2.console.log('incrementByObject之前', this.state.count)
* 和console.log('incrementByObject之后', this.state.count)
* 两句代码是在render方法和this.setState方法回调之前执行。不是
* 顺序执行的。所以是异步
*/
incrementByObject = () => {
console.log('incrementByObject之前', this.state.count)
this.setState({ count: 5 }, () => {
/**
* 这个方法没有参数,但是可以在这里获取更新之后state的值。
* callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
*/
console.log('incrementByObject', this.state.count)
})
console.log('incrementByObject之后', this.state.count)
}
/**
* 通过setTimeout实现this.setState方法的同步
* 执行顺序是
* 1.console.log('incrementByObject之前', this.state.count)
* 2.render
* 3.this.setState方法回调执行
* 4.console.log('incrementByObject之后', this.state.count)
*/
incrementByObjectAndSetTimeoutSync = () => {
setTimeout(() => {
this.incrementByObject()
})
}
/**
* 通过Promise实现this.setState方法的同步
* 执行顺序是
* 1.console.log('incrementByObject之前', this.state.count)
* 2.render
* 3.this.setState方法回调执行
* 4.console.log('incrementByObject之后', this.state.count)
*/
incrementByObjectAndPromiseSync = () => {
Promise.resolve().then(() => {
this.incrementByObject()
})
}
/**
* 通过dom事件实现this.setState方法的同步
* 执行顺序是
* 1.console.log('incrementByObject之前', this.state.count)
* 2.render
* 3.this.setState方法回调执行
* 4.console.log('incrementByObject之后', this.state.count)
*/
incrementByObjectAndClickSync = () => {
console.log('incrementByObjectAndClickSync',this.refs.bindClick)
this.refs.bindClick.onclick = () => {
this.incrementByObject()
}
}
/**
* 1.如果依赖原来的值,建议使用方法方式调用setState
* 2.console.log('incrementByFunction之前', this.state.count)
* 和console.log('incrementByFunction之后', this.state.count)
* 两句代码是在render方法和this.setState方法回调之前执行。不是
* 顺序执行的。所以是异步
*/
incrementByFunction = () => {
console.log('incrementByFunction之前', this.state.count)
this.setState(state => {
return { count: state.count + 1 }
}, () => {
/**
* 这个方法没有参数,但是可以在这里获取更新之后state的值。
* callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
*/
console.log('incrementByFunction', this.state.count)
})
console.log('incrementByFunction之后', this.state.count)
}
/**
* 1.console.log('componentDidMount之前', this.state.count)
* 和console.log('componentDidMount之后', this.state.count)
* 两句代码是在render方法和this.setState方法回调之前执行。不是
* 顺序执行的。所以是异步
*/
componentDidMount() {
console.log('componentDidMount之前', this.state.count)
this.setState({ count: 10 }, () => {
/**
* 这个方法没有参数,但是可以在这里获取更新之后state的值。
* callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
*/
console.log('componentDidMount', this.state.count)
})
console.log('componentDidMount之后', this.state.count)
}
render() {
const { count } = this.state
console.log('render', count)
return (
<div>
<h2>当前值是:{this.state.count}</h2>
<button onClick={this.incrementByObject}>点击我+1==ByObject</button>
<button onClick={this.incrementByFunction}>点击我+1==ByFunction</button>
<hr />
<button onClick={this.incrementByObjectAndSetTimeoutSync}>通过setTimeout回调实现同步</button>
<button onClick={this.incrementByObjectAndPromiseSync}>通过Promise回调实现同步</button>
<button onClick={this.incrementByObjectAndClickSync}>通过dom事件回调实现同步</button>
<button ref="bindClick">setState===Sync</button>
</div>
)
}
}
四、setState连续调用
import React, { Component } from 'react'
/**
* setState连续调用的时候,会出现合并的情况
*/
export default class index extends Component {
state = { count: 0 }
/**
* 调用顺序
* 1.console.log('incrementByObject之前', this.state.count) 0
* 2.console.log('incrementByObject之后', this.state.count) 0
* 3.render 1
* 4.console.log('incrementByObject1', this.state.count) 1
* 5.console.log('incrementByObject2', this.state.count) 1
*/
incrementByObject = () => {
console.log('incrementByObject之前', this.state.count)
this.setState({ count: this.state.count + 1 }, () => {
console.log('incrementByObject1', this.state.count)
})
this.setState({ count: this.state.count + 1 }, () => {
console.log('incrementByObject2', this.state.count)
})
console.log('incrementByObject之后', this.state.count)
}
/**
* 调用顺序
* 1.console.log('incrementByFunction之前', this.state.count) 0
* 2.console.log('incrementByFunction之后', this.state.count) 0
* 3.render 2
* 4.console.log('incrementByFunction1', this.state.count) 2
* 5.console.log('incrementByFunction2', this.state.count) 2
*/
incrementByFunction = () => {
console.log('incrementByFunction之前', this.state.count)
this.setState(state => {
return { count: state.count + 1 }
}, () => {
console.log('incrementByFunction1', this.state.count)
})
this.setState(state => {
return { count: state.count + 1 }
}, () => {
console.log('incrementByFunction2', this.state.count)
})
console.log('incrementByFunction之后', this.state.count)
}
componentDidMount() {
console.log('componentDidMount之后', this.state.count)
}
render() {
const { count } = this.state
console.log('render', count)
return (
<div>
<h2>当前值是:{this.state.count}</h2>
<button onClick={this.incrementByObject}>点击我+1==ByObject</button>
<button onClick={this.incrementByFunction}>点击我+1==ByFunction</button>
</div>
)
}
}