1. 程式人生 > >【譯】最新版本react元件生命週期詳解(v16.3.1)

【譯】最新版本react元件生命週期詳解(v16.3.1)

16版本的react對元件的生命週期函式進行了一些修改,在每個react元件中都有以下幾個生命週期方法~我們需要在不同階段進行討論。為了良好的閱讀體驗,請檢視github原文

元件生命週期概述

1.初始化

在元件初始化階段會執行
1. constructor
2. static getDerivedStateFromProps()
3. componentWillMount() / UNSAFE_componentWillMount()
4. render()
5. componentDidMount()

2.更新階段

propsstate的改變可能會引起元件的更新,元件重新渲染的過程中會呼叫以下方法:
1. componentWillReceiveProps()

/ UNSAFE_componentWillReceiveProps()
2. static getDerivedStateFromProps()
3. shouldComponentUpdate()
4. componentWillUpdate() / UNSAFE_componentWillUpdate()
5. render()
6. getSnapshotBeforeUpdate()
7. componentDidUpdate()

3.解除安裝階段

  1. componentWillUnmount()

4.錯誤處理

  1. componentDidCatch()

react生命週期圖示

react生命週期圖示

互動式展示

生命週期函式詳解

1.constructor(props)

react元件的建構函式在掛載之前被呼叫。在實現React.Component建構函式時,需要先在新增其他內容前,呼叫super(props),用來將父元件傳來的props繫結到這個類中,使用this.props將會得到。

官方建議不要在constructor引入任何具有副作用和訂閱功能的程式碼,這些應當在componentDidMount()中寫入。

constructor中應當做些初始化的動作,如:初始化state,將事件處理函式繫結到類例項上,但也不要使用setState()。如果沒有必要初始化state或繫結方法,則不需要構造constructor

,或者把這個元件換成純函式寫法。

當然也可以利用props初始化state,在之後修改state不會對props造成任何修改,但仍然建議大家提升狀態到父元件中,或使用redux統一進行狀態管理。

constructor(props) {
  super(props);
  this.state = {
    color: props.initialColor
  };
}

2.static getDerivedStateFromProps(nextProps, prevState)

getDerivedStateFromProps在元件例項化後,和接受新的props後被呼叫。他返回一個物件來更新狀態,或者返回null表示新的props不需要任何state的更新。

如果是由於父元件的props更改,所帶來的重新渲染,也會觸發此方法。

呼叫steState()不會觸發getDerivedStateFromProps()

3. componentWillMount() / UNSAFE_componentWillMount()

componentWillMount()將在react未來版本中被棄用。UNSAFE_componentWillMount()在元件掛載前被呼叫,在這個方法中呼叫setState()不會起作用,是由於他在render()前被呼叫。

為了避免副作用和其他的訂閱,官方都建議使用componentDidMount()代替。這個方法是用於在伺服器渲染上的唯一方法。

4.render()

render()方法是必需的。當他被呼叫時,他將計算this.propsthis.state,並返回以下一種型別:
1. React元素。通過jsx建立,既可以是dom元素,也可以是使用者自定義的元件。
2. 字串或數字。他們將會以文字節點形式渲染到dom中。
3. Portals。react 16版本中提出的新的解決方案,可以使元件脫離父元件層級直接掛載在DOM樹的任何位置。
4. null,什麼也不渲染
5. 布林值。也是什麼都不渲染,通常後跟元件進行判斷。

當返回null,false,ReactDOM.findDOMNode(this)將會返回null,什麼都不會渲染。

render()方法必須是一個純函式,他不應該改變state,也不能直接和瀏覽器進行互動,應該將事件放在其他生命週期函式中。
如果shouldComponentUpdate()返回falserender()不會被呼叫。

Fragments

你也可以在render()中使用陣列,如:(不要忘記給每個陣列元素新增key,防止出現警告)

render() {
  return [
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

換一種寫法,可以不寫key(v16++)

render() {
  return (
    <React.Fragment>
      <li>First item</li>
      <li>Second item</li>
      <li>Third item</li>
    </React.Fragment>
  );
}

5.componentWillReceiveProps()/UNSAFE_componentWillReceiveProps(nextProps)

官方建議使用getDerivedStateFromProps函式代替componentWillReceiveProps()。當元件掛載後,接收到新的props後會被呼叫。如果需要更新state來響應props的更改,則可以進行this.propsnextProps的比較,並在此方法中使用this.setState()

如果父元件會讓這個元件重新渲染,即使props沒有改變,也會呼叫這個方法。

react不會在元件初始化props時呼叫這個方法。呼叫this.setState也不會觸發。

6.shouldComponentUpdate(nextProps, nextState)

呼叫shouldComponentUpdate使react知道,元件的輸出是否受stateprops的影響。預設每個狀態的更改都會重新渲染,大多數情況下應該保持這個預設行為。

在渲染新的propsstate前,shouldComponentUpdate會被呼叫。預設為true。這個方法不會在初始化時被呼叫,也不會在forceUpdate()時被呼叫。返回false不會阻止子元件在state更改時重新渲染。

如果shouldComponentUpdate()返回falsecomponentwillupdate,rendercomponentDidUpdate不會被呼叫。

在未來版本,shouldComponentUpdate()將會作為一個提示而不是嚴格的指令,返回false仍然可能導致元件的重新渲染。

官方並不建議在shouldComponentUpdate()中進行深度查詢或使用JSON.stringify(),他效率非常低,並且損傷效能。

7.UNSAFE_componentWillUpdate(nextProps, nextState)

在渲染新的stateprops時,UNSAFE_componentWillUpdate會被呼叫,將此作為在更新發生之前進行準備的機會。這個方法不會在初始化時被呼叫。

不能在這裡使用this.setState(),也不能做會觸發檢視更新的操作。如果需要更新stateprops,呼叫getDerivedStateFromProps

8.getSnapshotBeforeUpdate()

在react render()後的輸出被渲染到DOM之前被呼叫。它使您的元件能夠在它們被潛在更改之前捕獲當前值(如滾動位置)。這個生命週期返回的任何值都將作為引數傳遞給componentDidUpdate()。

9.componentDidUpdate(prevProps, prevState, snapshot)

在更新發生後立即呼叫componentDidUpdate()。此方法不用於初始渲染。當元件更新時,將此作為一個機會來操作DOM。只要您將當前的props與以前的props進行比較(例如,如果props沒有改變,則可能不需要網路請求),這也是做網路請求的好地方。

如果元件實現getSnapshotBeforeUpdate()生命週期,則它返回的值將作為第三個“快照”引數傳遞給componentDidUpdate()。否則,這個引數是undefined

10.componentWillUnmount()

在元件被解除安裝並銷燬之前立即被呼叫。在此方法中執行任何必要的清理,例如使定時器無效,取消網路請求或清理在componentDidMount()中建立的任何監聽。

11.componentDidCatch(error, info)

錯誤邊界是React元件,可以在其子元件樹中的任何位置捕獲JavaScript錯誤,記錄這些錯誤並顯示回退UI,而不是崩潰的元件樹。錯誤邊界在渲染期間,生命週期方法以及整個樹下的建構函式中捕獲錯誤。

如果類元件定義了此生命週期方法,則它將成為錯誤邊界。在它中呼叫setState()可以讓你在下面的樹中捕獲未處理的JavaScript錯誤,並顯示一個後備UI。只能使用錯誤邊界從意外異常中恢復;不要試圖將它們用於控制流程。詳細

錯誤邊界只會捕獲樹中下面元件中的錯誤。錯誤邊界本身不能捕獲錯誤。

參考文件