1.关于setState 方法要注意的点
(1)参数及用法
- react不能直接修改
this.state
的值,需要使用this.setState()
方法 - setState()方法有两个参数
- 参数1:是对象类型, key是this.state中的key值 ,val是修改后的数据
- 参数2:是函数类型
(1)查看数据是否已经更新 (2)可以获取到数据更新后的最新的DOM结构
- 第一个参数有两种情况:
-1. 第一个参数 为对象
-2. 第一个参数 为方法this.setState({ isLiked: !this.state.isLiked })
当第一个参数为方法时,参数可以是上一次state的状态值和上一次props值this.setState( () =>{ return{ isLiked: !this.state.isLiked } })
this.setState((prevState,props)=>{ return{ isLiked:!prevState.isLiked } })
(2)为什么要用setState方法?
不能通过赋值直接修改state的值
如:this.state.isLiked = '不喜欢'
这种写法可以修改数据值,但是不会重新渲染界面-
state的更新是异步的
react为了优化性能,可能会将多个setState()合并成一个去更新,因为this.state 和 this.props是异步更新的,所以不能依据他们的值去计算下一个值。
错误如下:this.setState({ sum:this.state.count + this.props.num })
为此,可以使用参数为方法,此方法有两个参数,第一个参数是前一个状态,第二个参数是传入的props值。
正确如下:this.setState((prevState,props)=>{ return{ sum:this.state.count + this.props.num } })
state的更新会被合并
当你调用 setState(), React 将合并你提供的对象到当前的状态中。所以当State是一个多键值的结构时,可以单独更新其中的一个,此时会进行“差分”更新,不会影响其他的属性值。
(3)执行setState之后,就可以得到更新后的值吗?
可以通过一个例子得到结论:
class Lick extends Component {
constructor(){
super();
this.state= {
isLiked:false
}
}
handleLikedClick = ()=>{
this.setState(()=>{
console.log('内部state值',this.state.isLiked);
return {
isLiked: !this.state.isLiked
}
},()=>{
console.log('回调state值',this.state.isLiked)
});
console.log('外部state值',this.state.isLiked)
}
}
在修改setState执行之前,及之后,以及回调中可以得到此时的状态值
会发现,只有回调函数中才拿到了更新后的state值,所以也得出,若要在修改之后,在得到状态值,可以在setState方法的回调函数得到。
(4)执行setState之后,会立马更新state的值吗(执行过程)?
看一看看下面的代码:
function incrementMultiple() {
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
}
直观上来看,当上面的 incrementMultiple 函数被调用时,组件状态的 count 值被增加了3次,每次增加1,那最后 count 被增加了3。但是,实际上的结果只给 state 增加了1。
事实上,setState 方法与包含在其中的执行是一个很复杂的过程。
从 React 最初的版本到现在,也有无数次的修改。它的工作除了要更动 this.state 之外,还要负责触发重新渲染,这里面要经过 React 核心 diff 算法,最终才能决定是否要进行重渲染,以及如何渲染。而且为了批次与效能的理由,多个 setState 呼叫有可能在执行过程中还需要被合并,所以它被设计以延时的来进行执行是相当合理的。
在 React 的 setState 函数实现中,会根据一个变量isBatchingUpdates
(是否批量更新) 判断是直接更新 this.state 还是放到队列中回头再说,而 isBatchingUpdates 默认是 false,也就表示 setState 会同步更新 this.state。
但是,有一个函数 batchedUpdates
,这个函数会把 isBatchingUpdates 修改为 true,就会将this.state放入队列。
当 React 在调用事件处理函数之前就会调用这个 batchedUpdates,造成的后果,就是由 React 控制的事件处理过程 setState 不会同步更新 this.state。
由 React 控制的事件处理过程 setState会异步更新 this.state
也就是说,在 React 控制之外的情况, setState 会同步更新 this.state