捋一捋React的生命週期

前言:React 的版本從 v15 到 v16.3 ,再到v16.4,如今最新的版本是 v16.8了。其中最大的變化多是React Hooks的加入,而最使人困惑的倒是它的生命週期,新舊生命週期函數混雜在一塊兒,不免會讓許多新來者有不少困惑。因此這一篇咱們來分析一下 React 生命週期的演變及緣由,進一步理解其使用。react

組件生命週期的四個階段

  1. Initialization (初始化階段:組件實例的建立)
  2. Mounting (加載階段:組件插入 dom中)
  3. Updating (更新階段:屬性或狀態每改變一次都將會觸發一次,組件從新渲染。)
  4. Unmounting (卸載階段:組件卸載和銷燬)

老版生命週期(16.3以前的生命週期)

clipboard.png

Initialization (初始化階段:涉及4個鉤子函數)

這些方法會在組件初始化的時候被調用,只跟實例的建立有關。
若是用createReactClass進行建立,則還有getInitialState這些生命週期函數,但不多使用,咱們這裏不說起。算法

static defaultProps{} (getDefaultProps())

定義默認props,會和父組件傳下來的props進行合併,且以父組件中的props優先級更高,至關於{...defaultProps, props}segmentfault

static propTypes{} (getInitialState())

定義props的數據類型,能夠幫助咱們肯定其有效性,減小許多開發中沒必要要的錯誤。瀏覽器

constructor()

在加載階段前調用一次,進行 state 的初始化。性能優化

constructor(props){
    super(props)
}

super(props)用來調用父類的構建方法。網絡

Mounting (加載階段:涉及3個鉤子函數)

componentWillMount()

新版中爲UNSAFE_componentWillMount()dom

只在組件加載時調用,整個生命週期只調用一次,之後組件更新也不會調用,此時能夠修改 state。async

render()

react 中最重要的生命週期函數,建立虛擬 dom,並進行 diff 算法,更新 dom 樹也在此進行。因此不該該在此改變組件的狀態或者與瀏覽器進行交互。ide

注意:這個函數不能缺乏,若是不建立虛擬 dom,能夠return null函數

componentDidMount()

組件加載完成後當即調用,整個生命週期只調用一次,能夠獲取到更新後的 DOM,在此處能夠進行網絡請求等。

Updating (更新階段:涉及5個鉤子函數)

componentWillReceiveProps()

新版中爲UNSAFE_componentWillReceiveProps()

在組件加載後,若是有新的props傳遞過來,會先調用這個函數,能夠在這裏調用setState()修改state

componentWillReceiveProps(nextProps)

shouldComponentUpdate()

react中一個重要的性能優化點,組件接收到新的props或者state,返回true表示須要更新 dom,返回false阻止更新。

shouldComponentUpdate(nextProps, nextState)

componentWillUpdate()

新版中爲UNSAFE_componentWillUpdate()

組件加載時不調用,只有在組件須要更新(即shouldComponentUpdate返回true)時調用。

componentWillUpdate(nextProps, nextState)

注意:不能在這個方法中調用setState()修改state

render()

同上。

componentDidUpdate()

在組件更新完成後當即被調用,能夠進行網絡請求等。

componentDidUpdate(prevProps, prevState)

Unmounting (卸載階段:涉及1個鉤子函數)

componentWillUnmount()

在組件被卸載和銷燬以前調用,能夠在這裏處理任何須要的清理工做,好比解除定時器,取消已經發起的網絡請求,清理在componentDidMount函數中建立的 DOM 元素。

componentWillUnmount()

Error Handling(錯誤處理:涉及1個鉤子函數)

componentDidCatch()

錯誤邊界捕獲,在v16.0剛推出的時候新增長的一個生命週期函數,用於捕獲在子組件樹中任意地方發生的 JavaScript 錯誤,一個錯誤邊界不能捕獲它本身內部的錯誤。

componentDidCatch(error, info)

組件的基本寫法

import React, {Component} from 'React'

export default class OldReactComponent extends Componet{
    static defaultProps={}
    static propTypes={}
    constructor(props){
        super(props)
    }
    state={}
    componentWillMount(){}
    render(){
        return null
    }
    componentDidMount(){}
    componentWillReceivePorps(nextProps){}
    componentShouldUpdate(nextProps,nextState){
        return true
    }
    componentWillUpdate(nextProps,nextState){}
    componentDidUpdate(){}
    componentWillUnmount(){}
}

新版生命週期(16.4以後的生命週期)

clipboard.png

(帶UNSAFE_的函數在之後將會被丟棄,官方也不建議使用,這裏再也不列出。)

新版本中,新增了三個生命週期函數:

  • static getDerivedStateFromProps()
  • getSnapshotBeforeUpdate
  • static getDerivedStateFromError()

同時deprecate了一組生命週期API,包括:

  • componentWillReceiveProps
  • componentWillMount
  • componentWillUpdate

能夠看出除了shouldComponentUpdate以外,render 以前的全部生命週期都被消滅了。緣由是這些生命週期太多時候沒有被正確使用,並且在Fiber以後,若是要開啓async rendering,在render函數以前的全部函數,都有可能被執行屢次。

Initialization (初始化階段:涉及4個鉤子函數)

同上。

Mounting (加載階段:涉及3個鉤子函數)

static getDerivedStateFromProps()

由於是靜態方法,因此沒法訪問到組件實例。每次組件調用render前都會被調用,獲取新的propsstate(v16.3只會爲props的而調用,v16.4修正爲propsstate)以後,返回一個對象做爲新的state,若是返回null則表示不須要更新;配合componentDidUpdate,能夠覆蓋componentWillReceiveProps的全部用法。而且它應該是個純函數,沒有反作用(side effect)。

static getDerivedStateFromProps(props,state)

render()

同上。

componentDidMount()

同上。

Updating (更新階段:涉及5個鉤子函數)

static getDerivedStateFromProps()

同上。

shouldComponentUpdate()

同上。

render()

同上。

getSnapshotBeforeUpdate()

觸發時間: update發生的時候,在render以後,在組件dom渲染以前;返回一個值,做爲componentDidUpdate的第三個參數;配合componentDidUpdate, 能夠覆蓋componentWillUpdate的全部用法,經常使用於 scroll 位置的定位。

getSnapshotBeforeUpdate(prevProps, prevState)

componentDidUpdate()

同上。

Unmounting (卸載階段:涉及1個鉤子函數)

componentWillUnmount()

同上。

Error Handling(錯誤處理:涉及2個鉤子函數)

componentDidCatch()

同上。

static getDerivedStateFromError()

用於在「render」階段(非render函數)的錯誤捕獲,應該是個純函數,沒有反作用(side effect)。

static getDerivedStateFromError(error)

組件的基本寫法

import React, {Component} from 'React'

export default class OldReactComponent extends Componet{
    static defaultProps={}
    static propTypes={}
    constructor(props){
        super(props)
    }
    state={}
    static getDerivedStateFromProps(props,state){}
    render(){
        return null
    }
    componentDidMount(){}
    componentShouldUpdate(nextProps,nextState){
        return true
    }
    getSnapshotBeforeUpdate(prevProps, prevState){}
    componentDidUpdate(){}
    componentWillUnmount(){}
}

總結

  1. React新的生命週期新增static getDerivedStateFromPropsgetSnapshotBeforeUpdate並棄用componentWillMountcomponentWillReceivePropscomponetWillUpdate(這三個函數將在 React 17中刪除)。
  2. 新增static getDerivedStateFromError捕獲「render」階段的錯誤。

參考

幫你理清React的生命週期

React-新的生命週期(React16版本)

React v16.3以後的組件生命週期函數

清晰大圖請點擊這裏

相關文章
相關標籤/搜索