React中setState的怪異行為 ——setState沒有即時(shí)生效

setState可以說是React中使用頻率最高的一個(gè)函數(shù)了,我們都知道芒炼,React是通過管理狀態(tài)來實(shí)現(xiàn)對(duì)組件的管理的,當(dāng)this.setState()被調(diào)用的時(shí)候,React會(huì)重新調(diào)用render方法來重新渲染UI

但實(shí)際使用的時(shí)候觅丰,我們會(huì)發(fā)現(xiàn),有時(shí)候我們setState之后妨退,并沒有立刻生效妇萄,例如我們看一下以下的示例代碼

class Test extends Component {
 constructor(props) {
   super(props);
   this.state = {
     count: 0
   };
 }

 componentDidMount() {
   this.setState({count: this.state.count + 1});
   console.log(this.state.count); // 輸出0
   this.setState({count: this.state.count + 1});
   console.log(this.state.count); // 輸出0
   setTimeout(() => {
     this.setState({count: this.state.count + 1});
     console.log(this.state.count); // 輸出2
     this.setState({count: this.state.count + 1});
     console.log(this.state.count); // 輸出3
   }, 0);
 }

 render() {
   return <div> test </div>;
 }
}

開發(fā)過程中我們會(huì)發(fā)現(xiàn),在componentDidMount方法中咬荷,我們調(diào)用setState之后state的值并沒有立即改變冠句,但如果我們?cè)趕etTimeOut里面調(diào)用,我們卻能立刻就能獲得更新幸乒,原因就在于react中的使用了基于事務(wù)(傳送門懦底,關(guān)于事務(wù)原理的解析)的異步更新機(jī)制,但對(duì)于這個(gè)異步的理解罕扎,又跟ajax的異步有所不同聚唐,因?yàn)楫吘箁eact是一個(gè)js框架,所有的操作都是單線程的腔召,所有的操作杆查,都得按順序來,那么它具體是怎么實(shí)現(xiàn)的呢臀蛛?

我們都知道亲桦,對(duì)于dom的操作對(duì)性能的損耗是非常嚴(yán)重的,所以react為了提高整體的渲染性能浊仆,會(huì)將一次渲染周期中的state進(jìn)行合并客峭,在這個(gè)渲染周期中你對(duì)所有setState的所有調(diào)用都會(huì)被合并起來之后,再一次性的渲染氧卧,這樣可以避免頻繁的調(diào)用setState導(dǎo)致頻繁的操作dom桃笙,提高渲染性能。具體的實(shí)現(xiàn)方面沙绝,可以簡單的理解為react中存在一個(gè)狀態(tài)變量isBatchingUpdates搏明,當(dāng)處于渲染周期開始時(shí)鼠锈,這個(gè)變量會(huì)被設(shè)置成true,渲染周期結(jié)束時(shí)星著,會(huì)被設(shè)置成false购笆,react會(huì)根據(jù)這個(gè)狀態(tài)變量,當(dāng)出在渲染周期中時(shí)虚循,僅僅只是將當(dāng)前的改變緩存起來同欠,等到渲染周期結(jié)束時(shí),再一次性的全部render,横缔,具體的流程可以參照下面的流程圖


image.png

現(xiàn)在铺遂,我們回到最開始的問題,為什么一開始在componentDidMount中直接執(zhí)行setState會(huì)無法立刻得到更新呢茎刚,原因就在于襟锐,我們?cè)赾omponentDidMount中其實(shí)處于首次渲染的事務(wù)當(dāng)中,這次事務(wù)的渲染尚未完成膛锭,而首次渲染的時(shí)候會(huì)將isBatchingUpdates設(shè)置為true粮坞,這是我們?cè)赾omponentDidMount中調(diào)用setState,react會(huì)發(fā)現(xiàn)當(dāng)前事務(wù)尚未完成初狰,只會(huì)直接將修改后的state放入到dirtyComponents中莫杈,等待最終渲染周期完成時(shí),將所有的state進(jìn)行合并奢入,一次性render筝闹。而當(dāng)我們放在setTimeOut里面的時(shí)候,setTimeOut會(huì)將操作放到執(zhí)行隊(duì)列的最后方俊马,也就是說會(huì)等待渲染周期結(jié)束之后再進(jìn)行setState丁存,這個(gè)時(shí)候狀態(tài)變量已經(jīng)被重置回來了,所以此時(shí)我們的每一次setState都會(huì)立刻生效

那么柴我,問題來了解寝,當(dāng)我們?cè)阡秩局芷谥袌?zhí)行了setState之后,我們要如何獲取到最新的state的值呢艘儒,setTimeOut是一個(gè)方案聋伦,但是不太優(yōu)雅,有沒有其他方法呢界睁,我們注意到觉增,setState提供了一個(gè)回調(diào)函數(shù),我們只需要在回調(diào)里面獲取更新后的state即可翻斟,像這樣

componentDidMount() {
    this.setState({count: this.state.count + 1},()=>{
    console.log(this.state.count);//該是啥就是是啥
    }));
  }

————————————————
原文鏈接:https://blog.csdn.net/handsomexiaominge/article/details/86348235

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末逾礁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子访惜,更是在濱河造成了極大的恐慌嘹履,老刑警劉巖腻扇,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異砾嫉,居然都是意外死亡幼苛,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門焕刮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舶沿,“玉大人,你說我怎么就攤上這事配并±ǖ矗” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵荐绝,是天一觀的道長一汽。 經(jīng)常有香客問我,道長低滩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任岩喷,我火速辦了婚禮恕沫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纱意。我一直安慰自己婶溯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布偷霉。 她就那樣靜靜地躺著迄委,像睡著了一般。 火紅的嫁衣襯著肌膚如雪类少。 梳的紋絲不亂的頭發(fā)上叙身,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音硫狞,去河邊找鬼信轿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛残吩,可吹牛的內(nèi)容都是我干的财忽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼泣侮,長吁一口氣:“原來是場噩夢啊……” “哼即彪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起活尊,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤隶校,失蹤者是張志新(化名)和其女友劉穎琼蚯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惠况,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡遭庶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了稠屠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峦睡。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖权埠,靈堂內(nèi)的尸體忽然破棺而出榨了,到底是詐尸還是另有隱情,我是刑警寧澤攘蔽,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布龙屉,位于F島的核電站,受9級(jí)特大地震影響满俗,放射性物質(zhì)發(fā)生泄漏转捕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一唆垃、第九天 我趴在偏房一處隱蔽的房頂上張望五芝。 院中可真熱鬧,春花似錦辕万、人聲如沸枢步。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽醉途。三九已至,卻和暖如春砖茸,著一層夾襖步出監(jiān)牢的瞬間隘擎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工渔彰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嵌屎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓恍涂,卻偏偏與公主長得像宝惰,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子再沧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容