React是如何控制组件的状态,又是如何利用状态来管理组件的

在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值。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容