React Native 開發(fā) - setState與狀態(tài)機(jī)

state與狀態(tài)機(jī)思維

狀態(tài)機(jī)的四大概念践惑。

State 苔悦,狀態(tài)。一個狀態(tài)機(jī)至少要包含兩個狀態(tài)水援。例如上面燈泡的例子吮龄,有 燈泡亮和 燈泡滅兩個狀態(tài)盅藻。
Event 癞己,事件淘邻。事件就是執(zhí)行某個操作的觸發(fā)條件或者口令。對于燈泡儿惫,“打開開關(guān)”就是一個事件澡罚。
Action ,動作肾请。事件發(fā)生以后要執(zhí)行動作留搔。例如事件是“打開開關(guān)”,動作是“開燈”铛铁。編程的時候隔显,一個 Action 一般就對應(yīng)一個函數(shù)。
Transition 饵逐,變換括眠。也就是從一個狀態(tài)變化為另一個狀態(tài)。例如“開燈過程”就是一個變換倍权。

React將每一種UI的狀態(tài)都看做為一個簡單的狀態(tài)機(jī)掷豺,那么任意一個UI場景就是狀態(tài)機(jī)中的一種狀態(tài)。

根據(jù)決定狀態(tài)的狀態(tài)機(jī)變量的值薄声,React框架渲染出狀態(tài)機(jī)的當(dāng)前狀態(tài)——對于開發(fā)者來說当船,單個UI場景就被渲染出來了。隨著狀態(tài)機(jī)變量值的變化默辨,UI狀態(tài)機(jī)也在不停的改變狀態(tài)德频,UI場景也隨著不斷渲染。這樣一個過程可以很輕松的做到數(shù)據(jù)與UI保持一致缩幸。

在RN的開發(fā)中壹置,開發(fā)者需要將狀態(tài)機(jī)變量視為“不可變的常量”,在開發(fā)者的代碼中表谊,永遠(yuǎn)不要出現(xiàn) this.state.變量名 = value 這樣的語句钞护。這樣的語句對于JS來講是合法的并且可以被正確執(zhí)行,但是從RN開發(fā)原則的角度說爆办,它是不合法的难咕。當(dāng)開發(fā)者需要改變狀態(tài)機(jī)變量的值時,一定要并且只能使用this.setState函數(shù)押逼。

對于RN開發(fā)者來說步藕,RN開發(fā)的一個重要原則就是:
“努力讓自定義的RN組件成為無狀態(tài)的RN組件”惦界。
或者說在不影響程序結(jié)構(gòu)的情況下挑格,盡可能減少有狀態(tài)的React-native組件的數(shù)量。

那么沾歪,哪些RN組件必須有狀態(tài)機(jī)變量呢漂彤?
當(dāng)一個組件需要處理用戶的輸入,或者需要處理網(wǎng)絡(luò)側(cè)發(fā)給應(yīng)用程序的數(shù)據(jù),或者需要處理超時事件挫望,或者需要處理自己訂閱的事件消息等不可預(yù)知的輸入型事件時立润。它就必須要有對應(yīng)的狀態(tài)機(jī)變量。

努力讓用戶的自定義RN組件成為無狀態(tài)的RN組件媳板,減少狀態(tài)機(jī)變量的數(shù)量桑腮,可以讓代碼的框架更清晰。

一個好的設(shè)計思路是:創(chuàng)建多個只負(fù)責(zé)渲染數(shù)據(jù)的無狀態(tài)React-Native組件蛉幸,將它們封裝在一個有狀態(tài)的RN組件中破讨,并把這個有狀態(tài)的RN組件的狀態(tài)機(jī)變量的值通過props傳給無狀態(tài)的RN組件。這就是React-Redux的設(shè)計原理奕纫。

狀態(tài)機(jī)變量的合并

根據(jù)上面的狀態(tài)機(jī)思維提陶,當(dāng)我們需要重新渲染UI時,只要合并狀態(tài)機(jī)變量即可匹层,常見的合并狀態(tài)機(jī)變量的API有setState和forceUpdate隙笆。

forceUpdate

如果開發(fā)者因為某種原因,使得UI中可變數(shù)據(jù)的來源必須從狀態(tài)機(jī)變量和屬性外獲得升筏,那么就需要這個變量來進(jìn)行界面的強(qiáng)制刷新撑柔。

它會導(dǎo)致不經(jīng)優(yōu)化的全部刷新,即調(diào)用forceUpdate函數(shù)導(dǎo)致的重新渲染過程仰冠,將不會調(diào)用shouldComponentUpdate來檢查并重新渲染乏冀。因此會導(dǎo)致大量無意義的刷新,只要需要UI進(jìn)行立即刷新的特殊情況才需要使用洋只。(它是同步的函數(shù)辆沦,在UI線程上執(zhí)行刷新)

setState

與之不同的是 setState(nextState, callback) 函數(shù)在調(diào)用后并不會進(jìn)行同步的刷新,而是異步的刷新识虚,它需要經(jīng)過優(yōu)化的步驟肢扯,重新計算哪里發(fā)生了改變,哪里需要重新渲染担锤。所以蔚晨,需要指出的是如果setState中的需要合并的新的狀態(tài)機(jī)變量與原本的沒有任何的變化,它將不會進(jìn)行渲染肛循。

同時铭腕,因為setState是異步的,所以如果我們需要setState渲染后的某些屬性來進(jìn)行相應(yīng)的操作多糠,那么就需要使用回調(diào)函數(shù)累舷。例如下面的例子:

如果我們界面中進(jìn)行了控件的產(chǎn)生和銷毀,那么象征該控件的ref只有在被渲染到屏幕上后該組件的ref才存在夹孔,但是這就存在一個問題即setState是異步的被盈,我們執(zhí)行以下的操作就會報ref is undefined的錯誤:
this.setState({xxx:value});
// 特別的析孽,當(dāng)xxx與value變量名重名時,可以省略只怎,即setState({value})與setState({value:value})等價

this.refs.xxx

這是因為setState是異步的操作袜瞬,當(dāng)它被調(diào)用時主線程繼續(xù)向下執(zhí)行,但是這時還沒有渲染完成身堡,即ref為undefined的狀態(tài)邓尤,這時就要采用setState的回調(diào)函數(shù)來完成,它等價于componentDidUpdate贴谎,與componentUpdate相比較好的一點是裁赠,它可以在多個setState中根據(jù)更新的數(shù)據(jù)的不同定制不同的回調(diào)函數(shù),避免componentDidUpdate函數(shù)體過長赴精。
`
最后不會出現(xiàn)問題的調(diào)用方式就是:

this.setState({[key]:value},() => {
    this.ref[xxx]
});

shouldComponentUpdate

RN框架使用shouldComponentUpdate函數(shù)來判斷接下來是否進(jìn)行渲染佩捞,這個函數(shù)的原型是 boolean shouldComponentUpdate(nextProps,nextState)。這個函數(shù)會傳入兩個對象蕾哟,分別代表接下來渲染所基于的props與state一忱。

與數(shù)據(jù)庫中的觸發(fā)器很類似,在執(zhí)行shouldComponentUpdate這個函數(shù)時谭确,組件原本的props和state并沒有發(fā)生改變帘营,你還可以用this.state和this.props訪問它。所以可以進(jìn)行當(dāng)前狀態(tài)和更新狀態(tài)的比較來判斷是否需要進(jìn)行重新渲染逐哈。

如果RN組件實現(xiàn)了這個函數(shù)芬迄,那么在執(zhí)行重新渲染時,會先調(diào)用這個函數(shù)昂秃≠魇幔可以在這個函數(shù)中進(jìn)行一定的判斷,如果這個函數(shù)返回false肠骆,那么RN將放棄渲染該組件算途。

借鑒鏈接:https://blog.csdn.net/kkk96291/article/details/110659859

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蚀腿,隨后出現(xiàn)的幾起案子嘴瓤,更是在濱河造成了極大的恐慌,老刑警劉巖莉钙,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件廓脆,死亡現(xiàn)場離奇詭異,居然都是意外死亡磁玉,警方通過查閱死者的電腦和手機(jī)停忿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜀涨,“玉大人瞎嬉,你說我怎么就攤上這事『窳” “怎么了氧枣?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長别垮。 經(jīng)常有香客問我便监,道長,這世上最難降的妖魔是什么碳想? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任烧董,我火速辦了婚禮,結(jié)果婚禮上胧奔,老公的妹妹穿的比我還像新娘逊移。我一直安慰自己,他們只是感情好龙填,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布胳泉。 她就那樣靜靜地躺著,像睡著了一般岩遗。 火紅的嫁衣襯著肌膚如雪扇商。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天宿礁,我揣著相機(jī)與錄音案铺,去河邊找鬼。 笑死梆靖,一個胖子當(dāng)著我的面吹牛控汉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播返吻,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼暇番,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了思喊?” 一聲冷哼從身側(cè)響起壁酬,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎恨课,沒想到半個月后舆乔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡剂公,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年希俩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纲辽。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡颜武,死狀恐怖璃搜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鳞上,我是刑警寧澤这吻,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站篙议,受9級特大地震影響唾糯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鬼贱,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一移怯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧这难,春花似錦舟误、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至糖权,卻和暖如春堵腹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背星澳。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工疚顷, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人禁偎。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓腿堤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親如暖。 傳聞我的和親對象是個殘疾皇子笆檀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

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