關(guān)于this.setState()的那些事

在網(wǎng)上看了很多關(guān)于this.setState()的介紹,覺得受益匪淺,就總結(jié)了一些幫助自己理解的點讼稚,在此分享出來撩荣,如果有侵權(quán)的地方,請及時提醒田晚。

一、State的定義

狀態(tài)(state) 和 屬性(props) 類似,都是一個組件所需要的一些數(shù)據(jù)集合滤淳,但是它是私有的,并且由組件本身完全控制砌左,可以認為它是組件的“私有屬性(或者是局部屬性)”脖咐。

二、關(guān)于 setState() 有三件事是你應(yīng)該知道的汇歹。# 參考鏈接

1.不要直接修改 state(狀態(tài))

this.state.comment = 'Hello';

上述代碼并不會重新渲染組件屁擅,需要使用this.setState()代替:

this.setState({
  comment: 'Hello'
});

需要注意的是唯一可以分配 this.state 的地方是構(gòu)造函數(shù)

2.state(狀態(tài)) 更新可能是異步的

React 為了優(yōu)化性能产弹,有可能會將多個 setState() 調(diào)用合并為一次更新派歌。
因為this.propsthis.state 可能是異步更新的,你不能依賴他們的值計算下一個state(狀態(tài))痰哨。以下面的代碼為例:

this.setState({
  counter: this.state.counter + this.props.increment,
});

我們并不能通過上述代碼得到想要的值胶果,為了彌補這個問題,使用另一種 setState() 的形式斤斧,接受一個函數(shù)早抠。這個函數(shù)將接收前一個狀態(tài)作為第一個參數(shù),應(yīng)用更新時的 props 作為第二個參數(shù)折欠,代碼如下:

this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

3.state(狀態(tài))更新會被合并

當你調(diào)用 setState()贝或, React 將合并你提供的對象到當前的狀態(tài)中吼过。所以當State是一個多鍵值的結(jié)構(gòu)時,可以單獨更新其中的一個咪奖,此時會進行“差分”更新盗忱,不會影響其他的屬性值。

三羊赵、setState()的異步更新趟佃。# 原文鏈接

1.執(zhí)行setState()之后干了什么?

setState()方法通過一個隊列機制實現(xiàn)state更新昧捷,當執(zhí)行setState()的時候闲昭,會將需要更新的state合并之后放入狀態(tài)隊列,而不會立即更新this.state(可以和瀏覽器的事件隊列類比)靡挥。如果我們不使用setState而是使用this.state.key來修改序矩,將不會觸發(fā)組件的re-render。如果將this.state賦值給一個新的對象引用跋破,那么其他不在對象上的state將不會被放入狀態(tài)隊列中簸淀,當下次調(diào)用setState()并對狀態(tài)隊列進行合并時,直接造成了state丟失毒返。

2.setState()可以接受一個函數(shù)作為參數(shù)租幕?

setState() 不僅能夠接受一個對象作為參數(shù),還能夠接受一個函數(shù)作為參數(shù)拧簸。函數(shù)的參數(shù)即為 state 的前一個狀態(tài)以及 props劲绪。
React文檔中對setState的說明如下:

void setState (
      function|object nextState,
      [function callback]
)

上述代碼的第二個參數(shù)是一個回調(diào)函數(shù),在setState() 的異步操作結(jié)束并且組件已經(jīng)重新渲染的時候執(zhí)行盆赤。換句話說贾富,我們可以通過這個回調(diào)來拿到更新的state的值。

3.執(zhí)行setState()后能拿到最新的state值嗎弟劲?

以前在寫代碼時候祷安,總是遇到明明執(zhí)行過setState(),但是state的值卻不是最新的兔乞,那么如何解決這個問題呢汇鞭?

因為setState()函數(shù)接受兩個參數(shù),一個是一個對象庸追,就是設(shè)置的狀態(tài)霍骄,還有一個是一個回調(diào)函數(shù),是在設(shè)置狀態(tài)成功之后執(zhí)行的淡溯,所以我們可以通過回掉拿到最新的state值读整。代碼如下:

updateData = (newData) => {
    this.setState(
        { data: newData },
        () => {
            //這里打印的是最新的state值
            console.log(this.state.data);
        }
    );
}

4.setState()一定是異步更新嗎? **# 原文鏈接

我們先來看看下面的代碼:

function incrementMultiple() {
      this.setState({count: this.state.count + 1});
      this.setState({count: this.state.count + 1});
      this.setState({count: this.state.count + 1});
}

直觀上來看咱娶,當上面的 incrementMultiple 函數(shù)被調(diào)用時米间,組件狀態(tài)的 count 值被增加了3次强品,每次增加1,那最后 count 被增加了3屈糊。但是的榛,實際上的結(jié)果只給 state 增加了1。
事實上逻锐,setState 方法與包含在其中的執(zhí)行是一個很復(fù)雜的過程夫晌,從 React 最初的版本到現(xiàn)在,也有無數(shù)次的修改昧诱。它的工作除了要更動 this.state 之外晓淀,還要負責觸發(fā)重新渲染,這里面要經(jīng)過 React 核心 diff 算法盏档,最終才能決定是否要進行重渲染凶掰,以及如何渲染。而且為了批次與效能的理由妆丘,多個 setState 呼叫有可能在執(zhí)行過程中還需要被合并锄俄,所以它被設(shè)計以延時的來進行執(zhí)行是相當合理的。

setState執(zhí)行過程

在 React 的 setState 函數(shù)實現(xiàn)中勺拣,會根據(jù)一個變量 isBatchingUpdates 判斷是直接更新 this.state 還是放到隊列中回頭再說,而 isBatchingUpdates 默認是 false鱼填,也就表示 setState 會同步更新 this.state药有,但是,有一個函數(shù) batchedUpdates苹丸,這個函數(shù)會把 isBatchingUpdates 修改為 true愤惰,而當 React 在調(diào)用事件處理函數(shù)之前就會調(diào)用這個 batchedUpdates,造成的后果赘理,就是由 React 控制的事件處理過程 setState 不會同步更新 this.state宦言。

作者給出了下面的重點,趕緊拿起我的小本本記下商模。

由 React 控制的事件處理過程 setState 不會同步更新 this.state奠旺!
也就是說,在 React 控制之外的情況施流, setState 會同步更新 this.state响疚!

在大部分的使用情況下,我們都是使用了 React 庫中的表單組件瞪醋,例如 select忿晕、input、button 等等银受,它們都是 React 庫中人造的組件與事件践盼,是處于 React 庫的控制之下鸦采,比如組件原色 onClick 都是經(jīng)過 React 包裝。在這個情況下咕幻,setState 就會以異步的方式執(zhí)行渔伯。

總結(jié)就到這里了,由于我是技術(shù)渣渣谅河,能看懂和理解的只有這么多了咱旱,如果有讀者還想了解更多的內(nèi)容,可以點擊我文中的原文鏈接去看原作者的文章绷耍,如果遇到侵權(quán)的地方吐限,請聯(lián)系我,必刪褂始。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诸典,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子崎苗,更是在濱河造成了極大的恐慌狐粱,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胆数,死亡現(xiàn)場離奇詭異肌蜻,居然都是意外死亡,警方通過查閱死者的電腦和手機必尼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門蒋搜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人判莉,你說我怎么就攤上這事豆挽。” “怎么了券盅?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵帮哈,是天一觀的道長。 經(jīng)常有香客問我锰镀,道長娘侍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任互站,我火速辦了婚禮私蕾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘胡桃。我一直安慰自己踩叭,他們只是感情好,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著容贝,像睡著了一般自脯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斤富,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天膏潮,我揣著相機與錄音,去河邊找鬼满力。 笑死焕参,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的油额。 我是一名探鬼主播叠纷,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼潦嘶!你這毒婦竟也來了涩嚣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤掂僵,失蹤者是張志新(化名)和其女友劉穎航厚,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锰蓬,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡幔睬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芹扭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溪窒。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖冯勉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情摹芙,我是刑警寧澤灼狰,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站浮禾,受9級特大地震影響交胚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盈电,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一蝴簇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧匆帚,春花似錦熬词、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽歪今。三九已至,卻和暖如春颜矿,著一層夾襖步出監(jiān)牢的瞬間寄猩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工骑疆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留田篇,地道東北人。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓箍铭,卻偏偏與公主長得像泊柬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子坡疼,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

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

  • 說在前面 關(guān)于 react 的總結(jié)過去半年就一直碎碎念著要搞起來彬呻,各(wo)種(tai)原(lan)因(le)。心...
    陳嘻嘻啊閱讀 6,864評論 7 41
  • HTML模版 之后出現(xiàn)的React代碼嵌套入模版中柄瑰。 1. Hello world 這段代碼將一個一級標題插入到指...
    ryanho84閱讀 6,232評論 0 9
  • 本筆記基于React官方文檔闸氮,當前React版本號為15.4.0。 1. 安裝 1.1 嘗試 開始之前可以先去co...
    Awey閱讀 7,700評論 14 128
  • 相關(guān)知識 在租房這方面教沾,房屋中介其實分為中介和代理兩種蒲跨。 中介:幫你找來大量的客戶,你選擇客戶授翻,你和客戶簽訂租賃合...
    FifiZhuang閱讀 253評論 2 0
  • 很多年后或悲,每當抬頭仰望天空,小飛總會想起爺爺堪唐。 大雪下的緊巡语,村莊白茫茫一片,天變得暗了淮菠,冷風呼嘯著...
    行律閱讀 409評論 0 1