state

1.組件中用到的一個(gè)變量是不是應(yīng)該作為組件 State拍霜,可以通過下面的三條依據(jù)進(jìn)行判斷:

這個(gè)變量是否是通過Props從父組件中獲戎龆?如果是祠饺,那么它不是一個(gè)狀態(tài)越驻。 這個(gè)變量是否在組件的整個(gè)生命周期中都保持不變?如果是,那么它不是一個(gè)狀態(tài)伐谈。 這個(gè)變量是否可以通過其他狀態(tài)(State)或者屬性(Props)計(jì)算得到烂完?如果是,那么它不是一個(gè)狀態(tài)诵棵。

當(dāng)存在多個(gè)組件共同依賴一個(gè)狀態(tài)時(shí)抠蚣,一般的做法是==狀態(tài)上移==,將這個(gè)狀態(tài)放到這幾個(gè)組件的公共父組件中履澳。


2.State 的更新是異步的

???????調(diào)用setState嘶窄,組件的state并不會(huì)立即改變,setState只是把要修改的狀態(tài)放入一個(gè)隊(duì)列中距贷,React會(huì)優(yōu)化真正的執(zhí)行時(shí)機(jī)柄冲,并且React會(huì)出于性能原因,可能會(huì)將多次setState的狀態(tài)修改合并成一次狀態(tài)修改忠蝗。所以不要依賴當(dāng)前的State现横,計(jì)算下個(gè)State。當(dāng)真正執(zhí)行狀態(tài)修改時(shí)阁最,依賴的this.state并不能保證是最新的State戒祠,因?yàn)镽eact會(huì)把多次State的修改合并成一次,這時(shí)速种,this.state將還是這幾次State修改前的State姜盈。另外需要注意的事,同樣不能依賴當(dāng)前的Props計(jì)算下個(gè)狀態(tài)配阵,因?yàn)镻rops一般也是從父組件的State中獲取馏颂,依然無法確定在組件狀態(tài)更新時(shí)的值。

???????舉個(gè)例子棋傍,對(duì)于一個(gè)電商類應(yīng)用救拉,在我們的購物車中,當(dāng)我們點(diǎn)擊一次購買數(shù)量按鈕舍沙,購買的數(shù)量就會(huì)加1近上,如果我們連續(xù)點(diǎn)擊了兩次按鈕,就會(huì)連續(xù)調(diào)用兩次this.setState({quantity: this.state.quantity + 1})拂铡,在React合并多次修改為一次的情況下,相當(dāng)于等價(jià)執(zhí)行了如下代碼:

Object.assign(
  previousState,
  {quantity: this.state.quantity + 1},
  {quantity: this.state.quantity + 1}
)

???????于是乎葱绒,后面的操作覆蓋掉了前面的操作感帅,最終購買的數(shù)量只增加了1個(gè)。

???????如果你真的有這樣的需求地淀,可以使用另一個(gè)接收一個(gè)函數(shù)作為參數(shù)的setState失球,這個(gè)函數(shù)有兩個(gè)參數(shù),第一個(gè)是當(dāng)前最新狀態(tài)(本次組件狀態(tài)修改后的狀態(tài))的前一個(gè)狀態(tài)preState(本次組件狀態(tài)修改前的狀態(tài)),第二個(gè)參數(shù)是當(dāng)前最新的屬性props实苞。如下所示:

// 正確
this.setState((preState, props) => {
  counter: preState.quantity + 1;
})

3.State的更新方式

如有一個(gè)數(shù)組類型的狀態(tài)books豺撑,當(dāng)向books中增加一本書時(shí),使用數(shù)組的concat方法或ES6的數(shù)組擴(kuò)展語法(spread syntax):

在setState中修改數(shù)組時(shí)可以定義新數(shù)組等于state中的數(shù)組然后修改黔牵,也可以用preState方法來代替新數(shù)組

// 方法一:將state先賦值給另外的變量聪轿,然后使用concat創(chuàng)建新數(shù)組
var books = this.state.books;
this.setState({
  books: books.concat(['React Guide']);
})
 
// 方法二:使用preState、concat創(chuàng)建新數(shù)組
this.setState(preState => ({
  books: preState.books.concat(['React Guide']);
}))
 
// 方法三:ES6 spread syntax
this.setState(preState => ({
  books: [...preState.books, 'React Guide'];
}))

當(dāng)從books中截取部分元素作為新狀態(tài)時(shí)猾浦,使用數(shù)組的slice方法:

Slice(a,b)用來取數(shù)組中a開始到b-a之間的元素

// 方法一:將state先賦值給另外的變量陆错,然后使用slice創(chuàng)建新數(shù)組
var books = this.state.books;
this.setState({
  books: books.slice(1,3);
})
 
// 方法二:使用preState、slice創(chuàng)建新數(shù)組
this.setState(preState => ({
  books: preState.books.slice(1,3);
}))

當(dāng)從books中過濾部分元素后金赦,作為新狀態(tài)時(shí)音瓷,使用數(shù)組的filter方法:

// 方法一:將state先賦值給另外的變量,然后使用filter創(chuàng)建新數(shù)組
var books = this.state.books;
this.setState({
  books: books.filter(item => {
    return item != 'React';
  });
})
 
// 方法二:使用preState夹抗、filter創(chuàng)建新數(shù)組
this.setState(preState => ({
  books: preState.books.filter(item => {
    return item != 'React';
  });
}))

注意不要使用push绳慎、pop、shift漠烧、unshift偷线、splice等方法修改數(shù)組類型的狀態(tài),因?yàn)檫@些方法都是在原數(shù)組的基礎(chǔ)上修改沽甥,而concat声邦、slice、filter會(huì)返回一個(gè)新的數(shù)組摆舟。

當(dāng)狀態(tài)的類型是普通對(duì)象時(shí)有兩種方法:

1.使用ES6 的Object.assgin方法:

// 方法一:將state先賦值給另外的變量亥曹,然后使用Object.assign創(chuàng)建新對(duì)象
var owner = this.setState.owner;
this.setState({
  owner: Object.assign({}, owner, {name: 'Jason'});
})
 
// 方法二:使用preState、Object.assign創(chuàng)建新對(duì)象
this.setState(preState => ({
  owner: Object.assign({}, preState.owner, {name: 'Jason'});
}))

2.使用對(duì)象擴(kuò)展語法(object spread properties)

// 方法一:將state先賦值給另外的變量恨诱,然后使用對(duì)象擴(kuò)展語法創(chuàng)建新對(duì)象
var owner = this.setState.owner;
this.setState({
  owner: {...owner, {name: 'Jason'}};
})
 
// 方法二:使用preState媳瞪、對(duì)象擴(kuò)展語法創(chuàng)建新對(duì)象
this.setState(preState => ({
  owner: {...preState.owner, {name: 'Jason'}};
}))

總結(jié)一下,創(chuàng)建新的狀態(tài)對(duì)象的關(guān)鍵是照宝,避免使用會(huì)直接修改原對(duì)象的方法蛇受,而是使用可以返回一個(gè)新對(duì)象的方法。當(dāng)然厕鹃,也可以使用一些Immutable的JS庫兢仰,如Immutable.js,實(shí)現(xiàn)類似的效果剂碴。

那么把将,為什么React推薦組件的狀態(tài)是不可變對(duì)象呢?一方面是因?yàn)椴豢勺儗?duì)象方便管理和調(diào)試忆矛,了解更多可參考這里察蹲;另一方面是出于性能考慮,當(dāng)對(duì)象組件狀態(tài)都是不可變對(duì)象時(shí),我們?cè)诮M件的shouldComponentUpdate方法中洽议,僅需要比較狀態(tài)的引用就可以判斷狀態(tài)是否真的改變宗收,從而避免不必要的render調(diào)用。當(dāng)我們使用React提供的PureComponent時(shí)亚兄,更是要保證組件狀態(tài)是不可變對(duì)象混稽,否則在組件的shouldComponentUpdate方法中,狀態(tài)比較就可能出現(xiàn)錯(cuò)誤儿捧,因?yàn)镻ureComponent執(zhí)行的是淺比較(比較對(duì)象的引用)荚坞。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市菲盾,隨后出現(xiàn)的幾起案子颓影,更是在濱河造成了極大的恐慌,老刑警劉巖懒鉴,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诡挂,死亡現(xiàn)場離奇詭異,居然都是意外死亡临谱,警方通過查閱死者的電腦和手機(jī)璃俗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悉默,“玉大人城豁,你說我怎么就攤上這事〕危” “怎么了唱星?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長跟磨。 經(jīng)常有香客問我间聊,道長,這世上最難降的妖魔是什么抵拘? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任哎榴,我火速辦了婚禮,結(jié)果婚禮上僵蛛,老公的妹妹穿的比我還像新娘尚蝌。我一直安慰自己,他們只是感情好墩瞳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布驼壶。 她就那樣靜靜地躺著,像睡著了一般喉酌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天泪电,我揣著相機(jī)與錄音般妙,去河邊找鬼。 笑死相速,一個(gè)胖子當(dāng)著我的面吹牛碟渺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播突诬,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼苫拍,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了旺隙?” 一聲冷哼從身側(cè)響起绒极,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蔬捷,沒想到半個(gè)月后垄提,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡周拐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年铡俐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妥粟。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡审丘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出勾给,到底是詐尸還是另有隱情滩报,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布锦秒,位于F島的核電站露泊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏旅择。R本人自食惡果不足惜惭笑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望生真。 院中可真熱鬧沉噩,春花似錦、人聲如沸柱蟀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽长已。三九已至畜眨,卻和暖如春昼牛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背康聂。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國打工贰健, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人恬汁。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓伶椿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親氓侧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子脊另,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

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