理解React生命周期

constructor

React借用class類的constructor充當初始化鉤子仔夺。在我們類擴展任何其他具有已定義構(gòu)造函數(shù)的類的情況下,調(diào)用一個特殊的函數(shù)super非常重要忆植。
React中挡鞍,因為所有class組件都要繼承自Component類或者PureComponent類,因此和原生class寫法一樣历葛,要在constructor里首先調(diào)用super方法,才能獲得this嘀略。

deprecated—componentWillMount

componentWillMount與構(gòu)造函數(shù)沒有太大的區(qū)別——它也只在初始安裝生命周期中調(diào)用一次恤溶。

許多人會在這個函數(shù)中發(fā)送請求來獲取數(shù)據(jù),并期望在初次渲染就緒之前數(shù)據(jù)是可用的帜羊。

事實并非如此宏娄,盡管請求將在初次渲染之前被初始化,但在有時調(diào)用render之前它無法完成逮壁。

由于這一事實,不建議使用此函數(shù)可能會導致操作的副作用粮宛。

需要注意的是窥淆,在服務(wù)端渲染時調(diào)用此函數(shù),而在這種情況下巍杈,不會在服務(wù)器上調(diào)用對應(yīng)的componentDidMount忧饭,而是在客戶端上調(diào)用。

在這個函數(shù)中使用setState不會觸發(fā)render

static getDerivedStateFromProps(nextProps, prevState)

這個新的方法根據(jù)父組件傳來的props按需更新自己的state筷畦,主要是來代替componentWillReceiveProps词裤。
該方法定義的時候要加一個static關(guān)鍵字,訪問不到this對象鳖宾,在使用的時候吼砂,返回一個對象來增量更新組件的state(和setState非常像)

render

千萬不要在render生命周期鉤子里調(diào)用setState,因為setState會引發(fā)render鼎文,這樣就沒完沒了渔肩。

componentDidMount

在組件掛載之后調(diào)用,并且只調(diào)用一次拇惋。
因為這個函數(shù)只保證被調(diào)用一次周偎,所以它在這里執(zhí)行ajax請求簡直是完美。

deprecated—componentWillReceiveProps(nextProps)

在每次收到props(父組件重新渲染)的時候撑帖,在每個更新生命周期中都會調(diào)用此函數(shù)蓉坎,而且會傳遞所有的props,無論props的值是否發(fā)生了改變胡嘿,簡單來說就是組件收到新的props或者父組件重新渲染蛉艾,都會觸發(fā)這個方法。

如果某個組件的部分state是依賴于父組件中傳遞過來的props,這個函數(shù)是理想的伺通。

  • 注意:即使props沒有發(fā)生變化箍土,在componentWillReceiveProps也會被調(diào)用,這就需要開發(fā)者來判斷其值是否已經(jīng)發(fā)生改變罐监。
componentWillReceiveProps(nextProps) {
  if(nextProps.myProp !== this.props.myProps) {
    // do something
  }
}

shouldComponentUpdate(nextProps, nextState, nextContext)

默認情況下吴藻,所有基于Components的類在收到props時,statecontext改變時弓柱,都會觸發(fā)render沟堡。如果重新渲染組件涉及的計算比較復雜(比如生成圖表)或者由于某些性能原因而不推薦,則開發(fā)人員就需要來控制一下了矢空。當shouldComponentUpdate返回false的時候航罗,就不會觸發(fā)render

React還提供了一個PureComponent屁药,它與Component的區(qū)別是PureComponent自動實現(xiàn)了一個shouldComponentUpdate粥血。

shouldComponentUpdate暴露了兩個參數(shù),開發(fā)者可以通過比較propsnextProps酿箭、statenextState來判斷狀態(tài)到底有沒有發(fā)生改變复亏,再返回truefalse。要注意一下引用的坑缭嫡。

deprecated — componentWillUpdate(nextProps, nextState)

shouldComponentUpdate生命周期鉤子返回true缔御,或者調(diào)用this.forceUpdate之后,會立即執(zhí)行該生命周期鉤子妇蛀。
要特別注意耕突,componentWillUpdate生命周期鉤子每次更新前都會執(zhí)行,所以不能在這里調(diào)用setState评架,有可能會沒完沒了眷茁。
同樣,因為Fiber機制的引入纵诞,這個生命周期鉤子有可能會多次調(diào)用蔼卡。

componentDidUpdate(nextProps, nextState, snapshot)

componentWillUnmount

這是組件卸載之前的生命周期鉤子。

React的最佳實踐是挣磨,組件中用到的事件監(jiān)聽器雇逞、訂閱器、定時器都要在這里銷毀茁裙。

componentDidMount() {
    document.addEventListener('click', () => {});
}

componentDidCatch

在過去塘砸,組件內(nèi)部的JavaScript錯誤總是擾亂組件狀態(tài)以至于在下一次渲染中出現(xiàn)一些奇怪的錯誤,而且這些錯誤常常由應(yīng)用中一些更早的錯誤引起晤锥,然而 React 沒有提供一種在組件內(nèi)部解決這些問題的優(yōu)雅方案掉蔬,也不能從錯誤中恢復廊宪。

用戶界面某處的 JavaScript 錯誤不應(yīng)該使整個 APP 崩潰,為了解決這個問題女轿,React16 引進了一個新的概念 —— Error Boundaries

Error Boundaries 可以捕獲在其子組件樹里拋出的任何錯誤箭启,打印這些錯誤,并且返回一個展示錯誤的界面而不是崩潰掉的頁面蛉迹。Error Boundaries 可以在渲染過程中傅寡、在生命周期方法中、以及其子組件的 constructor 中捕獲錯誤

添加了一個叫做 componentDidCatch(error, info) 的新生命周期方法的組件就叫做 Error Boundaries

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  componentDidCatch(error, info) {
    // Display fallback UI
    this.setState({ hasError: true });
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

你仍然可以像正常組件一樣使用它

<ErrorBoundary>
  <App />
</ErrorBoundary>

componentDidCatch()方法就像是為組件定制的 JavaScript 中的 catch {} 代碼塊北救,只有通過 class 定義的組件才能成為 Error Boundaries荐操,在實踐中,絕大多數(shù)時候你都希望只定義一個 Error Boundary 然后在應(yīng)用的里使用珍策。

生命周期

React的生命周期鉤子托启,實際上只有三個過程:

  • 掛載
  • 更新
  • 卸載

老生命周期

  • 掛載

    • constructor
    • componentWillMount
    • render
    • componentDidMount


      掛載
  • 更新

    • componentWillReceiveProps
    • shouldComponentUpdate
    • componentWillUpdate
    • render
    • componentDidUpdate


      父組件觸發(fā)`render`

      `setState`觸發(fā)`render`

      調(diào)用`forceUpdate`觸發(fā)
  • 卸載

    • componentWillUnmount

新生命周期

  • 掛載
    • constructor
    • componentWillMount
    • render
    • componentDidMount
  • 更新
    • static getDerivedStateFromProps
    • shouldComponentUpdate
    • render
    • componentDidUpdate
  • 卸載
    • componentWillUnmount


      new-lifecycle.png

最后借一下大佬的圖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末攘宙,一起剝皮案震驚了整個濱河市屯耸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蹭劈,老刑警劉巖肩民,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異链方,居然都是意外死亡,警方通過查閱死者的電腦和手機灶搜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門祟蚀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人割卖,你說我怎么就攤上這事前酿。” “怎么了鹏溯?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵罢维,是天一觀的道長。 經(jīng)常有香客問我丙挽,道長肺孵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任颜阐,我火速辦了婚禮平窘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凳怨。我一直安慰自己瑰艘,他們只是感情好是鬼,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著紫新,像睡著了一般均蜜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上芒率,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天囤耳,我揣著相機與錄音,去河邊找鬼敲董。 笑死紫皇,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的腋寨。 我是一名探鬼主播聪铺,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼萄窜!你這毒婦竟也來了铃剔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤查刻,失蹤者是張志新(化名)和其女友劉穎键兜,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體穗泵,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡普气,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了佃延。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片现诀。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖履肃,靈堂內(nèi)的尸體忽然破棺而出仔沿,到底是詐尸還是另有隱情,我是刑警寧澤尺棋,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布封锉,位于F島的核電站,受9級特大地震影響膘螟,放射性物質(zhì)發(fā)生泄漏成福。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一荆残、第九天 我趴在偏房一處隱蔽的房頂上張望闷叉。 院中可真熱鬧,春花似錦脊阴、人聲如沸握侧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽品擎。三九已至埋合,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間萄传,已是汗流浹背甚颂。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留秀菱,地道東北人振诬。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像衍菱,于是被迫代替她去往敵國和親赶么。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348