setState是更新state刷新页面的接口,用于响应式,用于手动控制视图层刷新。
React 的核心思想是组件化的思想,应用由组件搭建而成,而组件中最重要的概念是State(状态),State是一个组件的UI数据模型,是组件渲染时的数据依据。比起vue将data中数据挂载到this上,react的状态仍然在state上。
setState
this.state通常只读,我们在react各种函数中使用setState完成this.state的更新并刷新UI视图,所以如果我们手动修改this.state就会被setState函数覆盖,无论是否修改不同属性。(这个props是类似的)
class App extends Component {
constructor(el) {
super(el)
this.state = {
clickCount: 0,
name: 'juejin',
age: 18
}
this.change = this.change.bind(this);
}
change(){
this.setState({clickCount: this.state.clickCount + 1})
}
render() {
return (
<div>
<p>{this.state.clickCount}</p>
<button onClick={this.change}>ok</button>
</div>
);
}
}
使用
我们编写的事件函数或回调函数中使用setState完成视图层和UI渲染数据更新。所以函数本身在构造函数内,在原型上。
- 参数一是需要更新的数据集合,参数二是回调函数:
this.setState({ clickCount: this.state.clickCount + 1 },()=>{
console.log(this.state.clickCount);
})
我们在回调函数中this.state获取到的是更新后的状态。
this指向
如果我们没有在constructor中修改函数的this指向,就不能使用setState方法,使用就会报错:
- 因为方法中的this已经不是组件里的this了,所以我们需要在constructor中修改函数的this指向
this.change = this.change.bind(this);
- 我们可以使用箭头函数来处理this问题:
change=()=>{
this.setState({clickCount: this.state.clickCount + 1})
}
同步异步
setState本身是同步的,但是多种情况下,react项目会将setState推迟执行:
change = () => {
console.log(this.state.clickCount)
this.setState({ clickCount: this.state.clickCount + 1 })
console.log(this.state.clickCount)
}
componentWillUpdate()
render()
componentDidUpdate()
我通过执行生命周期函数打印发现,setState真正生效是componentWillUpdate生命周期函数后,在render之前
。所以render会重新编译模板刷新视图层。
- 所以我们不能在setState后立马使用this.state去获去状态,应该
在componentDidUpdate和setState的回调函数中使用this.state
。
避免死循环
前面提到在事件函数或回调函数中调用setState进行状态更新,但是为了避免进入update的死循环中,我们应该避免在componentWillUpdate、render、componentDidUpdate去更新状态
,因为一旦更新状态就会重新执行componentWillUpdate、render、componentDidUpdate生命周期函数。
通常循环50次react项目就会报错抛出bug。
除了使用setState修改state会引起当前组件刷新外,我们还可以修改props值来触发子组件刷新。