在React16.8之前,React通过this.state来访问state,通过this.setState()方法来更新state。当this.setState()被调用的时候,React会重新调用render方法来重新渲染UI。state是React中的重要概念。React是通过状态管理来实现对组件的管理。那么,React是如何控制组件的状态,又是如何利用状态来管理组件的呢?
一、合成事件中setState
在jsx中常见的onClick、onChange这些都是合成事件
scala
classAppextendsComponent{state = {val:0} increment = () => {this.setState({val:this.state.val+1})// 输出的是更新之前的valconsole.log(this.state.val)// 0 } render() {return(
{`Counteris: ${this.state.val}`} </div> ) }}
当你在 increment中调用 setState之后去console.log的时候,是属于try代码块中的执行,但是由于是合成事件,try代码块执行完state并没有更新,所以你输入的结果是更新前的state值,这就导致了所谓的"异步",但是当你的try代码块执行完的时候(也就是你的increment合成事件),这个时候会去执行 finally里的代码,在 finally中执行了performSyncWork方法,这个时候才会去更新你的state 并且渲染到UI上。
二、生命周期函数中的setState
scala
classAppextendsComponent{state = {val:0} componentDidMount() {this.setState({val:this.state.val+1})// 输出的还是更新之前的值console.log(this.state.val)// 0 } render() {return( <div>{`Counteris: ${this.state.val}`} </div> ) }}
其实还是和合成事件一样,当componentDidmount执行的时候,react内部并没有更新,执行完componentDidmount后才去commitUpdateQueue更新。这就导致你在componentDidmount中setState完去console.log拿的结果还是更新前的值。
三、原生事件中的setState
scala
classAppextendsComponent{state = {val:0} changeValue = () => {this.setState({val:this.state.val+1})// 输出的是更新后的值!!!console.log(this.state.val)// 1 } componentDidMount() {document.body.addEventListener('click',this.changeValue,false) } render() {return( <div>{`Counteris: ${this.state.val}`} </div> ) }}
patek-shanghai.wbiao120.com
patek-shs.biaoshouhou.cn
patek-shenzhen.buchererweixiu.com
patek-shs.hidcwatch.com
patek-shenzhen.watchgz.cn
patek-shs.hntwx.cn
patek-shenzhen.aysza.cn
patek-shs.watchjwf.cn
patek-shenzhen.zzjshd.com
patek-shs.shmwatch.cn
patek-shenzhen.watch-service.com.cn
patek-shs.zhcxb.cn
patek-shs.jshdvip.com
patek-sys.iwatch4s.com
patek-shenzhen.jhpwd.cn
patek-shs.wzjshd.com
patek-sys.jws-watch.com
patek-shenzhen.watchwb.cn
patek-shs.watch-hdl.com
patek-whs.hdl-watch.com
patek-shenzhen.watchhdli.cn
patek-shs.watchrhf.cn
patek-whs.jshdsh.com
patek-shenzhen.watchda.cn
patek-shs.csjshd.com
patek-gebs.jshdkm.com
patek-hzs.xajshdzb.com
patek-shs.watch51.com
patek-gebs.jshdcq.com
patek-hzs.watchjt.com
patek-shs.jshdsx.com
patek-wxs.guoshew.com
patek-wxs.jsddshwx.com
patek-hzs.hljjshd.com
patek-tys.watchsc.com
patek-wxs.hbwatch.cn
patek-hzs.watchwx5.com
patek-hks.watchwd.com
patek-qds.gzomegawatch.com
patek-njs.watchlj.cn
patek-nts.watchk1.top
patek-qds.watchjwi.cn
patek-njs.watchjwd.cn
patek-cqs.watchjwb.cn
patek-fss.watchae.com
patek-njs.szwatchpg.com
patek-dls.swatchstar.top
patek-fss.shrolexwatch.com
patek-njs.rogerweixiu.com
patek-sz.vay.net.cn
原生事件是指非react合成事件,原生自带的事件监听addEventListener,或者也可以用原生js、jq直接document.querySelector().onclick这种绑定事件的形式都属于原生事件。
原生事件的调用栈就比较简单了,因为没有走合成事件的那一大堆,直接触发click事件,到requestWork,在requestWork里由于expirationTime === Sync的原因,直接走了performSyncWork 去更新,并不像合成事件或钩子函数中被return,所以当你在原生事件中setState后,能同步拿到更新后的state值。
四、setTimeout中的setState
scala
classAppextendsComponent{state = {val:0} componentDidMount() { setTimeout(_ => {this.setState({val:this.state.val+1})// 输出更新后的值console.log(this.state.val)// 1},0) } render() {return( <div>{`Counteris: ${this.state.val}`} </div> ) }}
在setTimeout中去setState并不算是一个单独的场景,它是随着你外层去决定的,因为你可以在合成事件中setTimeout,可以在钩子函数中setTimeout ,也可以在原生事件setTimeout,但是不管是哪个场景下,基于event loop的模型下, setTimeout中里去setState总能拿到最新的state值。