setState(nextState, callback)
这是UI更新最常用的方法,合并新的state到现有的state。
常规方式
nextState
可以为一个对象,包含0个或多个要更新的key。最简单的用法为:
this.setState({
key1: value1,
key2: value2
});
这种方式能应付大部分的应用场景,但是看看下面这种情况:
this.setState({
count: this.state.count + 1
});
this.setState({
count: this.state.count + 1
});
最后得到的count却是不可控的。因为 setState
不会立即改变 this.state
,而是挂起状态转换,调用 setState
方法后立即访问 this.state
可能得到的是旧的值。
setState
方法不会阻塞state更新完毕
第二个 setState
可能还没等待第一次的state更新完毕就开始执行了,所以最后count可能只加了1。
这时 setState
的第二个参数就派上用场了,第二个参数是state更新完毕的回调函数
this.setState({
count: this.state.count + 1
}, () => {
this.setState({
count: this.state.count + 1
});
});
不过看起来很怪, es6
中可以使用 Promise
更优雅的使用这个函数,封装一下 setState
function setStateAsync(nextState){
return new Promise(resolve => {
this.setState(nextState, resolve);
});
}
上面的例子就可以这样写
async func() {
...
await this.setStateAsync({count: this.state.count + 1});
await this.setStateAsync({count: this.state.count + 1});
}
顺眼多了。
函数方式
nextState
也可以是一个 function
,称为状态计算函数,结构为 function(state, props) => newState
。这个函数会将每次更新 加入队列 中,执行时通过当前的 state
和 props
来获取新的 state
。那么上面的例子就可以这样写
this.setState((state, props) => {
return {count: state.count + 1};
});
this.setState((state, props) => {
return {count: state.count + 1};
});
每次更新时都会提取出当前的state,进行运算得到新的state,就保证了数据的同步更新。
控制渲染
默认调用 setState
都会重新渲染视图,但是通过 shouldComponentUpdate()
函数返回 false
来避免重新渲染。
如果可变对象无法在 shouldComponentUpdate()
函数中实现条件渲染,则需要控制 newState
与 prevState
不同时才调用 setState
来避免不必要的重新渲染。http://www.tuicool.com/articles/UZ3YBvb