1. 不用直接修改this.state
比如this.state.value=1
因为setState通过一个队列机制实现state更新,当执行setState时,会将需要更新的state合并后放入状态队列,而不会立即更新this.state。队列机制可以高效批量的更新state。如果直接修改this.state的值(不会触发render),而不用setState,那么改state将不会被放入状态队列。当下次调用setState并对状态队列进行合并时,将会忽略之前被修改的state,造成无法预知的错误。
2. 不能使用setState的生命周期
不能在shouldComponentUpdate、componentWillUpdate生命周期里使用setState,这会造成循环调用风险,造成死循环
3.setState 什么时候是同步的,什么时候是异步的
在React中,如果是由React引发的事件处理(比如通过onClick引发的事件处理),以及生命周期函数调用setState不会同步更新this.state,除此之外的setState调用会同步执行this.state。所谓“除此之外”,指的是绕过React通过addEventListener直接添加的事件处理函数,还有通过setTimeout/setInterval产生的异步调用。
原因:在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,而isBatchingUpdates默认是false,也就表示setState会同步更新this.state,但是,有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,而当React在调用事件处理函数之前就会调用这个batchedUpdates,造成的后果,就是由React控制的事件处理过程setState不会同步更新this.state。
题目:
class App extends React.Component{
constructor(){
super();
this.state={
value: 0
}
}
componentDidMount(){
this.setState({value:this.state.value+1})
console.log(this.state.value)
this.setState({value:this.state.value+1})
console.log(this.state.value)
setTimeout(()=>{
this.setState({value:this.state.value+1})
console.log(this.state.value)
this.setState({value:this.state.value+1})
console.log(this.state.value)
},0)
}
render(){
console.log('render',this.state.value)
return <div>{this.state.value}</div>
}
}
ReactDOM.render(
<App/>,
document.getElementById('root')
);
输出
render 0
0
0
render 1
render 2
2
render 3
3