setState注意点
setState()
不会立刻改变 this.state
,而是创建一个即将处理的 state
转变。在调用该方法之后访问 this.state
可能会返回现有的值。
1. setState不保证同步
一般是异步的,在某些情况下也是可以同步更新的。同步更新
对 setState
的调用没有任何同步性的保证,并且调用可能会为了性能收益批量执行。
2. setState会造成不必要的渲染
造成不必要渲染的原因:
新的
state
其实和之前的是一样的。这个问题通常可以通过shouldComponentUpdate
来解决。也可以用pure render
或者其他的依赖库解决这个问题。通常发生改变的
state
是和渲染有关的,但是也有例外。比如,有些数据是根据某些状态来显示的。有些
state
和渲染一点关系都没有。有一些state
可能是和事件、timer ID
有关的。
setState()
将总是触发一次重绘,除非在 shouldComponentUpdate()
中实现了条件渲染逻辑。如果可变对象被使用了,但又不能在 shouldComponentUpdate()
中实现这种逻辑,仅在新 state
和之前的 state
存在差异的时候调用 setState()
可以避免不必要的重新渲染。
3.setState并不能很有效的管理所有的组件状态
根据原因3:有些
state
和渲染一点关系都没有。有一些state
可能是和事件、timer ID
有关的。
并不是所有的组件状态都应该用 setState
来进行保存和更新的。复杂的组件可能会有各种各样的状态需要管理。用 setState
来管理这些状态不但会造成很多不需要的重新渲染,也会造成相关的生命周期钩子一直被调用,从而造成很多奇怪的问题。
如何在setState后直接获取修改后的值
①传入对应的参数,不通过this.state获取
②使用回调函数
setState
方法接收一个 function
作为回调函数。这个回调函数会在 setState
完成以后直接调用,这样就可以获取最新的 state
。对于之前的例子,就可以这样:
onSelect(value) {
this.setState({
selection: value
}, this.fireOnSelect)
}
fireOnSelect() {
if (typeof this.props.onSelect === "function")
this.props.onSelect(this.state.selection) /* not what you expected..*/
}
③使用setTimeout
在 setState
使用 setTimeout
来让 setState
先完成以后再执行里面内容。这样子:
onSelect(value) {
this.setState({
selection: value
});
setTimeout(this.fireOnSelect, 0);
}
fireOnSelect() {
if (typeof this.props.onSelect === "function")
this.props.onSelect(this.state.selection) /* not what you expected..*/
}
总结
和渲染无关的状态尽量不要放在 state
中来管理
通常 state
中只来管理和渲染有关的状态 ,从而保证 setState
改变的状态都是和渲染有关的状态。这样子就可以避免不必要的重复渲染。其他和渲染无关的状态,可以直接以属性的形式保存在组件中,在需要的时候调用和改变,不会造成渲染。
避免不必要的修改,当 state
的值没有发生改变的时候,尽量不要使用 setState
。虽然 shouldComponentUpdate
和 PureComponent
可以避免不必要的重复渲染,但是还是增加了一层 shallowEqual
的调用,造成多余的浪费。