什么是state
React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。组件的任何UI改变,都可以从State的变化中反映出来;State中的所有状态都用于反映UI的变化,不应有多余状态。
- state来自内部状态,是组件对象最重要的属性,其值是对象,可以包含多个数据
- 可以通过更新组件的state来更新对应的页面显示(重新进行组件渲染),不必操作DOM
- 当页面发生变化时,用state来记录页面变化
什么样的变量应该作为组件的state呢
- 可以通过props从父组件中获取的变量不应该做为组件State。
- 这个变量如果在组件的整个生命周期中都保持不变就不应该作为组件State。
- 通过其他状态(State)或者属性(Props)计算得到的变量不应该作为组件State。
- 没有在组件的render方法中使用的变量不用于UI的渲染,那么这个变量不应该作为组件的State 。这种情况下,这个变量更适合定义为组件的一个普通属性。
state的使用方法
1.初始化state
constructor(props) {
super(props);
this.state={
key:value,
...
}
}
2.更新state
更新state调用以下方法
this.setState({
key:value
}) ;
注意,千万不能直接this.state.key=XXX; 这样做不会重新渲染页面,另外setState()是异步的,也就是你调用了setState()之后,React就开始准备去更新了,中间计算会可能会有一定的延时。
比如说:
//反例 这样是错误的
this.setState({
counter: this.state.count + this.props.add,
});
//正确的例子
this.setState((prevState, props) => ({
counter: prevState.count + props.add
}))
3、调用diff算法
这一步是在2步的基础上的,setState()会触发diff算法最终确定是否要更新
setState的使用方法
先看一个例子,点击累加
import React, { Component } from "react";
class App extends Component {
state = {
count: 0,
};
AddCount = () => {
this.setState({
count: this.state.count + 1,
});
};
handleAdd = () => {
this.AddCount();
this.AddCount();
this.AddCount();
console.log(this.state.count);
};
render() {
return (
<div>
<button onClick={this.AddCount}>AddCount</button>
<button onClick={this.handleAdd}>handleAdd</button>
<br />
<h1>{this.state.count}</h1>
</div>
);
}
}
export default App;
这是我们初始界面
当我们点击一下AddCount按钮 数字由0变为1
而当我们点击handleAdd时,数字并未变成4,而是变为1
当我们把AddCount函数改为
AddCount() {
this.setState((prevState) => {
return {count: prevState.count + 1}
});
}
再次点击handleAdd,数字变为5,成功加3
修改前后又有什么区别呢? 区别在于 传入一个更新函数
,就可以访问当前状态值。 setState调用是 批量处理
的,因此可以让更新建立在彼此之上,避免冲突。那为什么第一种方式就不可以呢?
setState为什么不会同步更新组件?
首先我们要知道
- setState
不会立刻改变
React组件中state的值. - setState 通过
触发一次组件的更新
来引发重绘
. - 多次 setState 函数调用产生的效果会
合并
。
重绘指的就是引起 React 的更新生命周期函数4个函数:
shouldComponentUpdate
(被调用时this.state没有更新;如果返回了false,生命周期被中断,虽然不调用之后的函数了,但是state仍然会被更新)componentWillUpdate
(被调用时this.state没有更新)render
(被调用时this.state得到更新)componentDidUpdate
如果说每一次setState调用都要走一编生命周期,这必然会导致效率问题。React会将setState的效果放在队列中,积攒着一次引发更新的过程,减少对 Virtual DOM 和 DOM 树的操作,用于提高性能。
查阅一些资料后发现,某些操作还是可以同步更新 this.state的
setState 什么时候会执行同步更新
?
在React中,如果是由React引发的事件处理(比如通过onClick引发的事件处理),调用 setState 不会同步更新 this.state,除此之外的setState调用会同步执行this.state。
所谓“除此之外”,指的是绕过React通过 addEventListener
直接添加的事件处理函数,还有通过setTimeout
|| setInterval
产生的异步调用。
简单一点说, 就是经过React 处理的事件是不会同步更新
this.state的. 通过 addEventListener
|| setTimeou
t/setInterval
的方式处理的则会同步更新
。
结语:本文借鉴了很多大佬博客中的思路,非常感谢大佬们的无私分享!愿互联网共享精神之光永远闪耀!