react之組件生命周期


四個階段

  • 初始化
  • 運行中
  • 銷毀
  • 錯誤處理(16.3以后)
  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()

各個生命周期詳解

(1)constructor

  • React組件的構造函數在掛在之前被調用。
  • 調用super(props),用來將父組件傳來的props綁定到這個類中,使用this.props將會得到。
  • constructor中應當做些初始化的動作,如:初始化state,將事件處理函數綁定到類實例上,但也不要使用setState()
    使用場景:
    • 初始化state數據
    • 定義函數修改this指向
      constructor(props) {
          super(props);
          this.state = {
              isLiked: props.isLiked
          };
          this.handleFun=this.handleFun.bind(this)
      }
      

(2)static getDerivedStateFromProps(nextProps, prevState)
React 16.3 的版本中 getDerivedStateFromProps 的觸發范圍是和 16.4^ 是不同的,主要區別是在 setStateforceUpdate 時會不會觸發,具體可以看這個生命全周期圖
使用場景:

  • 無條件的根據 prop 來更新內部 state,也就是只要有傳入 prop 值, 就更新 state
  • 只有 prop 值和 state 值不同時才更新 state 值。
Class ColorPicker extends React.Component {
    state = {
        color: '#000000'
    }
    static getDerivedStateFromProps (props, state) {
        if (props.color !== state.color) {
            return {
                color: props.color
            }
        }
        return null
    }
    ... // 選擇顏色方法
    render () {
        .... // 顯示顏色和選擇顏色操作
    }
}

純在問題:
現在我們可以這個顏色選擇器來選擇顏色,同時我們能傳入一個顏色值並顯示。如果我們傳入一個顏色值后,再使用組件內部的選擇顏色方法,我們會發現顏色不會變化,一直是傳入的顏色值。

這是使用這個生命周期的一個常見 bug。為什么會發生這個 bug 呢?在開頭有說到,在 React 16.4^ 的版本中 setStateforceUpdate 也會觸發這個生命周期,所以內部 state 變化后,又會走 getDerivedStateFromProps 方法,並把 state 值更新為傳入的 prop。

Class ColorPicker extends React.Component {
    state = {
        color: '#000000',
        prevPropColor: ''
    }
    static getDerivedStateFromProps (props, state) {
        if (props.color !== state.prevPropColor) {
            return {
                color: props.color
                prevPropColor: props.color
            }
        }
        return null
    }
    ... // 選擇顏色方法
    render () {
        .... // 顯示顏色和選擇顏色操作
    }
}

注意點:

  • 因為這個生命周期是靜態方法,同時要保持它是純函數,不要產生副作用。
  • 在使用此生命周期時,要注意把傳入的 prop 值和之前傳入的 prop 進行比較(這個 prop 值最好有唯一性,或者使用一個唯一性的 prop 值來專門比較)。
  • 不使用 getDerivedStateFromProps,可以改成組件保持完全不可控模式,通過初始值和 key 值來實現 prop 改變 state 的情景。

(3) componentWillMount() / UNSAFE_componentWillMount()

  • componentWillMount()將在React未來版本(官方說法 17.0)中被棄用UNSAFE_componentWillMount()在組件掛載前被調用,在這個方法中調用setState()不會起作用,是由於他在render()前被調用。

(4)render()
當他被調用時,他將計算this.propsthis.state,並返回以下一種類型:

  • React元素。通過jsx創建,既可以是dom元素,也可以是用戶自定義的組件。
  • 字符串或數字。他們將會以文本節點形式渲染到dom中。
  • Portals。react 16版本中提出的新的解決方案,可以使組件脫離父組件層級直接掛載在DOM樹的任何位置。
  • null,什么也不渲染
  • 布爾值。也是什么都不渲染。

注意:返回null,false,ReactDOM.findDOMNode(this)將會返回null,什么都不會渲染
render()方法必須是一個純函數,他不應該改變state,也不能直接和瀏覽器進行交互,應該將事件放在其他生命周期函數中。
如果shouldComponentUpdate()返回falserender()不會被調用。

(5)componentDidMount
組件被裝配后立即調用。
應用場景:

  • 通常在這里進行ajax請求
  • 初始化第三方的dom庫

(6)componentWillReceiveProps()/UNSAFE_componentWillReceiveProps(nextProps)
建議使用getDerivedStateFromProps函數代替

  • 當組件掛載后,接收到新的props后會被調用
  • 如果需要更新state來響應props的更改,則可以進行this.propsnextProps的比較,並在此方法中使用this.setState()
  • 如果父組件會讓這個組件重新渲染,即使props沒有改變,也會調用這個方法。
  • React不會在組件初始化props時調用這個方法。調用this.setState也不會觸發。

(7) shouldComponentUpdate(nextProps, nextState)

  • 渲染新的propsstate前,shouldComponentUpdate會被調用默認為true
  • 這個方法不會在初始化時被調用,也不會在forceUpdate()時被調用。返回false不會阻止子組件在state更改時重新渲染。
  • 如果shouldComponentUpdate()返回falsecomponentWillUpdate,rendercomponentDidUpdate不會被調用。

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

//下次的props和state數據
shouldComponentUpdate(nextProps,nextState){
    if(nextProps.data==this.props.data){
        return false
    }
    return true
}

(8) UNSAFE_componentWillUpdate(nextProps, nextState)
渲染新的stateprops時,UNSAFE_componentWillUpdate會被調用.
將此作為在更新發生之前進行准備的機會。這個方法不會在初始化時被調用
不能在這里使用this.setState(),也不能做會觸發視圖更新的操作。如果需要更新stateprops,調用getDerivedStateFromProps

(9) getSnapshotBeforeUpdate()
render()后的輸出被渲染到DOM之前被調用。

  • 它使您的組件能夠在它們被潛在更改之前捕獲當前值(如滾動位置)。
  • 這個生命周期返回的任何值都將作為參數傳遞給componentDidUpdate()。

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

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

(11) componentWillUnmount()

在組件被卸載並銷毀之前立即被調用。
在此方法中執行任何必要的清理,例如使定時器無效,取消網絡請求或清理在componentDidMount中創建的任何監聽。

(12) componentDidCatch(error, info)

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

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

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

PureComponent

PureComponent里如果接收到的新屬性或者是更改后的狀態和原屬性、原狀態相同的話,就不會去重新render了
在里面也可以使用shouldComponentUpdate,,而且。
是否重新渲染以shouldComponentUpdate的返回值為最終的決定因素。

import React, { PureComponent } from 'react'
class YourComponent extends PureComponent {
  ……
}

ref

對組件真正實例的引用,其實就是ReactDOM.render()返回的組件實例,ref可以掛載到組件上也可以是dom元素上。

  • 掛到組件(class聲明的組件)上的ref表示對組件實例的引用。不能在函數式組件上使用 ref 屬性,因為它們沒有實例:
  • 掛載到dom元素上時表示具體的dom元素節點。
import React, { Component, createRef } from 'react'
import ReactDOM from 'react-dom'

class App extends Component {
  constructor() {
    super()
    // 創建inputRef
    this.inputRef = createRef()
  }
  componentDidMount () {
    console.log(this.inputRef.current) // <input type="text">
  }
  render () {
    return (
  		<div>
        {/* 關聯ref和dom */}
        <input type="text" ref={this.inputRef} />
      </div>
  	)
  }
}
ReactDOM.render(
	<App/>,
  document.getElementById('root')


免責聲明!

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



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