React Native State(狀態(tài))使用詳解

BG:

目前的Component仍然在react框架中嗦董,也就是說(shuō)React Native使用的Component是react框架中的組件,而Component有兩大數(shù)據(jù)管理核心State和Props瘦黑。也就是說(shuō)即使你僅僅想用React Native開(kāi)發(fā)APP京革,你也需要去了解React的相關(guān)知識(shí),比如Component幸斥、State和Props匹摇,本文主要介紹State的使用。

React 把組件看成是一個(gè)狀態(tài)機(jī)(State Machines)甲葬。通過(guò)與用戶的交互廊勃,實(shí)現(xiàn)不同狀態(tài),然后渲染 UI经窖,讓用戶界面和數(shù)據(jù)保持一致供搀。
React 里,只需更新組件的 state钠至,然后根據(jù)新的 state 重新渲染用戶界面(不要操作 DOM)。

一.初始化 this.state

在組件的 類構(gòu)造函數(shù)(class constructor) 中初始化 this.state

export default class StatePage extends Component {
    constructor(props) {
        super(props);
        this.state = {  
            name : '張三',
            age:0,
         };
    };
}

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

二棉钧、this.setState()

1.setState的原理:

image.png

這只是一個(gè)簡(jiǎn)單的原理圖,setState背后的實(shí)現(xiàn)的詳細(xì)過(guò)程需要借助React.js源代碼和調(diào)用堆棧去查看涕蚤。

2.setState引發(fā)的Component的更新過(guò)程:

setState會(huì)觸發(fā)Component的以下4個(gè)生命周期方法宪卿,并依次執(zhí)行:

shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate

shouldComponentUpdate返回的是trueorfalse決定了當(dāng)前組件是否在state或props改變后是否進(jìn)行render。shouldComponentUpdate默認(rèn)返回的是true万栅,也就是當(dāng)前組件在setState或props改變后會(huì)進(jìn)行render佑钾,刷新UI。

3.this.state何時(shí)才被更新烦粒?

要想觀察this.state何時(shí)被更新休溶,需要我們?nèi)ピ谙嚓P(guān)生命周期方法中去進(jìn)行打印,而觀察的結(jié)果是這樣的:

當(dāng)shouldComponentUpdate返回true時(shí):

1.當(dāng)shouldComponentUpdate函數(shù)被調(diào)用的時(shí)候扰她,this.state沒(méi)有得到更新;
2.當(dāng)componentWillUpdate函數(shù)被調(diào)用的時(shí)候兽掰,this.state依然沒(méi)有得到更新;
3.直到render函數(shù)被調(diào)用的時(shí)候方面,this.state才得到更新油讯。

當(dāng)shouldComponentUpdate返回false時(shí):

1.本次shouldComponentUpdate函數(shù)被調(diào)用的時(shí)候欧漱,this.state沒(méi)有得到更新;
2.當(dāng)shouldComponentUpdate函數(shù)返回false攘蔽,此時(shí)更新過(guò)程會(huì)被中斷揪惦,render函數(shù)也不會(huì)被調(diào)用,但這時(shí)候React不會(huì)放棄掉對(duì)this.state的更新的壹哺,所以雖然不調(diào)用render倾剿,依然會(huì)更新this.state,在下次觸發(fā)shouldComponentUpdate時(shí)可以看到打印的this.state已經(jīng)更新熏挎。

綜上所述:直到render函數(shù)調(diào)用時(shí)(或者shouldComponentUpdate返回false速勇,再次在shouldComponentUpdate函數(shù)中)才得到更新后的this.state。

三婆瓜、setState使用:

執(zhí)行setState時(shí)快集,會(huì)將需要更新的state合并后放入狀態(tài)隊(duì)列,而不會(huì)立刻更新state廉白,隊(duì)列機(jī)制可以批量更新state个初。

1. setState的幾種場(chǎng)景:

(1).批量更新的典型,合并猴蹂、異步setState:
clickBtn=()=>{
        this.setState({
            name:'王五',
        });
        this.setState({
            age:30
        });
      this.setState({
            age:20
        });
}

合并是淺合并院溺,所以 第二次this.setState({age }) 不會(huì)把 this.state.name 沖掉,但會(huì)完全替換上一次this.state.age 的值磅轻。

以上代碼只會(huì)觸發(fā)1次render,并且在render函數(shù)調(diào)用時(shí)this.state.age的值才被更新且是20珍逸。也就是多次的setState會(huì)被合并,并且單個(gè)屬性的多次setState只有最后一次的更新會(huì)生效聋溜。

(2).非批量更新的典型谆膳,定時(shí)器中setState:
componentWillMount() {
        console.log(`StatePage--componentWillMount`);
        this.testTimer = setTimeout(
            ()=>{
                    this.setState({
                        age: this.state.age + 1,
                     });
                     this.setState({
                        age: this.state.age + 1,
                     });

                     this.setState({
                        age: this.state.age + 1,
                     });
            },
            0,
          );
   }

以上代碼會(huì)觸發(fā)3次render,并且每次this.state.age的值都會(huì)加1。

定時(shí)器中setState,對(duì)應(yīng)了上面setState的原理圖中的非bathUpdate分支撮躁。

(3)漱病、依賴this.props 和 this.state的值更新this.state:

因?yàn)?this.props 和 this.state 可能是異步更新的,你不能依賴他們的值計(jì)算下一個(gè)state(狀態(tài))把曼。
錯(cuò)誤寫(xiě)法:

    this.setState({
        age: this.state.age + this.props.baseAge,
     });

以上代碼可能導(dǎo)致 age(年齡)更新失斞蠲薄!

正確寫(xiě)法:
setState()接收一個(gè)函數(shù)嗤军,而不是一個(gè)對(duì)象注盈。該函數(shù)接收前一個(gè)狀態(tài)值作為第 1 個(gè)參數(shù),前一個(gè)props值作為第 2 個(gè)參數(shù)叙赚, 并將更新后的值進(jìn)行回調(diào)老客,也就是利用上一次狀態(tài)的age和props中的age進(jìn)行計(jì)算來(lái)更新的age:

this.setState((state, props) => ({
        age: state.age + props.baseAge,
    }));

在上面使用了一個(gè)箭頭函數(shù),但是也可以使用一個(gè)常規(guī)的函數(shù):

// 正確
this.setState(function(state, props) {
  return {
    counter:state.age + props.baseAge,
  };
});
(4)震叮、setState回調(diào)函數(shù):
this.setState({age: 23}, ()=> {
   console.log(this.state.age);//23
});

`setState的回調(diào)函數(shù)中可以獲取到已經(jīng)更新后的state沿量,相當(dāng)于componentDidUpdate函數(shù)或render函數(shù)中獲取更新后的state。

四冤荆、數(shù)據(jù)自頂向下流動(dòng)

無(wú)論作為父組件還是子組件朴则,它都無(wú)法獲悉一個(gè)組件是否有狀態(tài),同時(shí)也不需要關(guān)心另一個(gè)組件是定義為函數(shù)組件還是類組件。

這就是 state(狀態(tài)) 經(jīng)常被稱為 本地狀態(tài) 或 封裝狀態(tài)的原因乌妒。 它不能被擁有并設(shè)置它的組件 以外的任何組件訪問(wèn)汹想。

一個(gè)組件可以選擇將 state(狀態(tài)) 向下傳遞,作為其子組件的 props(屬性):

 <StateComponent name={this.state.name} age = {this.state.age}/>

子組件StateComponent通過(guò) props(屬性) 接收了父組件傳遞的name和age的值撤蚊,但它仍然不能獲知該值是來(lái)自于父組件的 state(狀態(tài)) 古掏,還是 父組件 的 props(屬性),或者是父組件中直接手動(dòng)創(chuàng)建的侦啸。

五槽唾、總結(jié):

1.不要使用 this.state 來(lái)直接修改 state,state值雖然會(huì)被更改光涂,但不會(huì)觸發(fā)render庞萍;
2.setState可能是異步的,不會(huì)立刻改變React組件中state的值忘闻;
3.React 為了優(yōu)化性能钝计,有可能會(huì)將多個(gè) setState() 調(diào)用合并為一次更新
4.setState通過(guò)引發(fā)一次組件的更新過(guò)程來(lái)引發(fā)重新繪制;
5.不能依賴this.props 和 this.state的值計(jì)算下一個(gè)state(狀態(tài))齐佳;
6.定時(shí)器中多次setState不會(huì)被合并私恬,state的值會(huì)被立即更新;
7.setState可能會(huì)引發(fā)不必要的渲染炼吴,你可以在shouldComponentUpdate(object nextProps, object nextState)函數(shù)中根據(jù)實(shí)際情況決定是否觸發(fā)render本鸣。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市硅蹦,隨后出現(xiàn)的幾起案子荣德,更是在濱河造成了極大的恐慌,老刑警劉巖提针,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異曹傀,居然都是意外死亡辐脖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)皆愉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)嗜价,“玉大人,你說(shuō)我怎么就攤上這事幕庐【米叮” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵异剥,是天一觀的道長(zhǎng)瑟由。 經(jīng)常有香客問(wèn)我,道長(zhǎng)冤寿,這世上最難降的妖魔是什么歹苦? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任青伤,我火速辦了婚禮,結(jié)果婚禮上殴瘦,老公的妹妹穿的比我還像新娘狠角。我一直安慰自己,他們只是感情好蚪腋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布丰歌。 她就那樣靜靜地躺著,像睡著了一般屉凯。 火紅的嫁衣襯著肌膚如雪立帖。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,590評(píng)論 1 305
  • 那天神得,我揣著相機(jī)與錄音厘惦,去河邊找鬼。 笑死哩簿,一個(gè)胖子當(dāng)著我的面吹牛宵蕉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播节榜,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼羡玛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了宗苍?” 一聲冷哼從身側(cè)響起稼稿,我...
    開(kāi)封第一講書(shū)人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎讳窟,沒(méi)想到半個(gè)月后让歼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丽啡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年谋右,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片补箍。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡改执,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出坑雅,到底是詐尸還是另有隱情辈挂,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布裹粤,位于F島的核電站终蒂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜后豫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一悉尾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挫酿,春花似錦构眯、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至葱弟,卻和暖如春壹店,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芝加。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工硅卢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人藏杖。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓将塑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蝌麸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子点寥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

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

  • 作為一個(gè)合格的開(kāi)發(fā)者,不要只滿足于編寫(xiě)了可以運(yùn)行的代碼来吩。而要了解代碼背后的工作原理敢辩;不要只滿足于自己的程序...
    六個(gè)周閱讀 8,448評(píng)論 1 33
  • 40、React 什么是React弟疆?React 是一個(gè)用于構(gòu)建用戶界面的框架(采用的是MVC模式):集中處理VIE...
    萌妹撒閱讀 1,016評(píng)論 0 1
  • 說(shuō)在前面 關(guān)于 react 的總結(jié)過(guò)去半年就一直碎碎念著要搞起來(lái)戚长,各(wo)種(tai)原(lan)因(le)。心...
    陳嘻嘻啊閱讀 6,873評(píng)論 7 41
  • 使用 create-react-app 快速構(gòu)建 React 開(kāi)發(fā)環(huán)境 項(xiàng)目的目錄結(jié)構(gòu)如下: React JSX ...
    majun00閱讀 510評(píng)論 0 0
  • 根據(jù)共讀計(jì)劃怠苔,本周(6.18-6.24)我通過(guò)電子書(shū)閱讀了《番茄工作法圖解-簡(jiǎn)單易行的時(shí)間管理法》的前三章...
    墨藍(lán)色彩閱讀 244評(píng)論 0 0