圖解React組件生命周期


一、組件生命周期

每個react類組件都包含“生命周期方法”(function組件是沒有生命周期方法的),你可以重寫這些方法,以便於在運行過程中特定的階段執行這些方法。在接下來的文章中,生命周期方法的書寫會遵照如下規則,以方便大家理解。

1、加粗生命周期方法表示常用的生命周期方法,開發中會經常使用到。

2、未加粗的生命周期方法表示罕見的生命周期方法,開發中很少會用到。

3、畫中橫線的生命周期方法表示即將過期的方法,開發中應避免使用。

4、若一定要使用即將失效的生命周期方法,可以參考官方文檔。

首先通過一幅圖來看下react組建的全部生命周期(version: ^16.4,之前的版本會略有區別)。

 

二、掛載

當組件實例被創建並插入 DOM 中時,被稱為組件掛載,其生命周期調用順序如下:

  • constructor()
    static getDerivedStateFromProps()
    UNSAFE_componentWillMount()
    render()
    componentDidMount()

 

1. constructor(props)  

在 React 組件掛載之前,會調用它的構造函數。在為 React.Component 子類實現構造函數時,應在其他語句之前前調用super(props)。否則,this.props在構造函數中可能會出現未定義的 bug。

通常,在 React 中,構造函數僅用於以下兩種情況:

  1. 通過給this.state賦值對象來初始化內部 state。
  2. 為事件處理函數綁定實例

如果不初始化 state 且不進行方法綁定,則不需要為 React 組件實現構造函數。

 

2. static getDerivedStateFromProps(props, state)  

getDerivedStateFromProps會在調用 render 方法之前調用,並且在初始掛載及后續更新時都會被調用。它應返回一個對象來更新 state,如果返回 null 則不更新任何內容。此方法無權訪問組件實例。如果你需要,可以通過提取組件 props 的純函數及 class 之外的狀態,在getDerivedStateFromProps()和其他 class 方法之間重用代碼。

 

3. render()  

render()方法是 class 組件中唯一必須實現的方法。該函數應該為純函數,這意味着在不修改組件 state 的情況下,每次調用時都返回相同的結果,並且它不會直接與瀏覽器交互。

如需與瀏覽器進行交互,請在componentDidMount()或其他生命周期方法中執行你的操作。保持render()為純函數,可以使組件更容易思考。

 

4. componentDidMount()  

componentDidMount()會在組件掛載后(插入 DOM 樹中)立即調用。依賴於 DOM 節點的初始化應該放在這里。如需通過網絡請求獲取數據,此處是實例化請求的好地方。

這個方法是比較適合添加訂閱的地方。如果添加了訂閱,請不要忘記在componentWillUnmount()里取消訂閱。

 

三、更新

當組件的 props 或 state 發生變化時會觸發更新。組件更新的生命周期調用順序如下:

  • static getDerivedStateFromProps()
    shouldComponentUpdate()
    UNSAFE_componentWillReceiveProps()
    UNSAFE_componentWillUpdate()
    render()
    getSnapshotBeforeUpdate()
    componentDidUpdate()

1、shouldComponentUpdate(nextProps, nextState)  

該方法是控制組件是否應該被更新。如果方法返回false則后續的生命周期方法將全部被跳過,該方法會接收nextProps 和nextState,可以通過比較this.props 和nextProps、this.state和nextState來決定是否要重新渲染組件,來對組件進行性能優化。你應該考慮使用內置的 PureComponent 組件,而不是手動編寫 shouldComponentUpdate()

官網中不建議在 shouldComponentUpdate() 中進行深層比較或使用 jsON.stringify()。這樣非常影響效率,且會損害性能。

2、getSnapshotBeforeUpdate(prevProps, prevState)  

getSnapshotBeforeUpdate() 在最近一次渲染輸出(提交到 DOM 節點)之前調用。它使得組件能在發生更改之前從 DOM 中捕獲一些信息(例如,滾動位置)。此生命周期的任何返回值將作為參數傳遞給 componentDidUpdate()。

3、componentDidUpdate(prevProps, prevState, snapshot)  

componentDidUpdate() 會在更新后會被立即調用。首次渲染不會執行此方法。

當組件更新后,可以在此處對 DOM 進行操作。如果你對更新前后的 props 進行了比較,也可以選擇在此處進行網絡請求。(例如,當 props 未發生變化時,則不會執行網絡請求)

componentDidUpdate(prevProps) {
  // 典型用法(不要忘記比較 props): if (this.props.userID !== prevProps.userID) { this.fetchData(this.props.userID); } }

你也可以在 componentDidUpdate() 中直接調用 setState(),但請注意它必須被包裹在一個條件語句里,正如上述的例子那樣進行處理,否則會導致死循環。

 

四、卸載

componentWillUnmount()

componentWillUnmount()會在組件卸載及銷毀之前直接調用。在此方法中執行必要的清理操作,例如,清除 timer,取消網絡請求或清除在componentDidMount()中創建的訂閱等。

 

五、錯誤處理

static getDerivedStateFromError()

static getDerivedStateFromError(error) { // 更新 state 使下一次渲染可以顯示降級 UI return { hasError: true }; } 

此生命周期會在后代組件拋出錯誤后被調用。 它將拋出的錯誤作為參數,並返回一個值以更新 state,你可以通過判斷state中的某個字段,來顯示降級UI

componentDidCatch()

此生命周期在后代組件拋出錯誤后被調用,可以用於日志記錄。 它接收兩個參數:

  1. error—— 拋出的錯誤。
  2. info—— 帶有componentStack key 的對象
componentDidCatch(error, info) {
  logToMyService(info.componentStack);
}

豌豆資源搜索網站https://55wd.com 廣州vi設計公司http://www.maiqicn.com


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM