首頁 >資訊 >

當前快訊:React筆記-生命周期(七)

時間:2023-05-15 09:40:24     來源: 博客園
React筆記-生命周期(七)

生命周期值React組件從裝載到卸載的全過程 在這個過程中React提供了多個內置函數供開發者在不同階段執行需要的邏輯

狀態組件由3個階段組成 掛載階段(MOUNTING) 更新階段(UPDATING) 卸載階段(UNMOUNT)

從縱向劃分為2個階段 Render階段 Commit階段


【資料圖】

Render階段 純凈且無副作用 會被React暫停 終止 重新啟動

Commit階段 可以使用DOM 有副作用

掛載階段constructor

構造函數(這個并不是react生命周期)

觸發時機

在組件初始化時觸發一次

構造函數因為在組件初始化時觸發 所以是初始化state最佳位置

static getDerivedStateFromProps

觸發時機

組件實例化后 重新渲染前

因此父組件更新 props變化 state更新 都會調用該函數

/**   *   * @param {*} nextProps 當前的props   * @param {*} prevState 修改前的state   * 該生命周期函數必須有返回值   * 它需要返回一個對象來更新 State   */static getDerivedStateFromProps(nextProps, prevState) {    if (nextProps.num) {      return {        ...prevState,        num: nextProps.num * 2      }    }    return prevState;  }

注意:

該生命周期函數是一個靜態函數 所以函數內無法訪問指向當前實例對象的this該生命周期函數被設計成靜態方法的目的是為了保持該方法的純粹 能夠起到限制開發者訪問 this 也就是實例的作用 這樣就不能在里面調用實例方法或者 setState 以破壞該生命周期函數的功能原本該生命周期函數是被設計成 初始化、父組件更新 和 接收到 Props 才會觸發,現在只要渲染就會觸發,也就是 初始化 和 更新階段 都會觸發componentWillMount

(此生命周期函數在React v17被正式廢棄)

觸發時機

在構造函數和裝載組件(將 DOM 樹渲染到瀏覽器中)之間觸發

注意

在此生命周期函數里使用 setState 同步設置組件內部狀態 state 將不會觸發重新渲染避免在該方法中引入任何的副作用(Effects)或訂閱(Subscription)。對于這些使用場景,建議提前到構造函數中
render(mounting階段)

渲染函數(這個并不是react生命周期)

作用: 僅用于渲染的純函數 返回值取決于state和props(并不是真實渲染 返回的是一個JSX描述文件 真實渲染取決于所有組件渲染函數后)

注意

不能在函數中任何修改 state、props、請求數據等具有副作用的操作不能讀寫 DOM 信息不能和瀏覽器進行交互(例如 setTimeout)
componentDidMount

觸發時機

組件完全掛載后(插入DOM樹中)立即調用 后面不會再次執行這個函數

使用場景

渲染DOM記載數據網絡請求

為什么在這個階段進行網絡請求

componentDidMount 這個階段已經完成了 render,commit 階段狀態已經穩定,在這個階段更新狀態(state)不會造成沖突

實現思路

在 contructor 函數中 通過 Promise 來進行數據的請求 并且綁定到當前實例對象上 然后在 componentDidMount 中執行 Promise 把數據更新到 state 上

class Life extends React.component {  componentDidMount () {  }}
更新階段componentWillReceiveProps

此生命周期函數將在React v17正式廢棄 推薦使用 static getDerivedStateFromProps()代替

觸發時機

父組件的渲染函數被調用 不論props是否改變 在渲染函數中被渲染的子組件都會經歷更新階段并觸發該生命周期函數state更新不會觸發該函數
/* nextProps 當前的props*/componentWillReceiveProps(nextProps) {   }
shouldComponentUpdate

目前官方已經提供React.PureComponent 用來替代React.Component替代手寫這個方法(不需要開發者自己實現shouldComponentUpdate,就可以進行簡單的判斷來提升性能)

觸發時機

因為 state 和 props 變化而更新時 在重新渲染前該生命周期函數都會觸發

使用場景

/**   *    * @param {*} nextProps 當前的props   * @param {*} nextState 當前的state   * @returns      根據邏輯判斷返回 true 表示繼續進行組件渲染,否則將停止組件渲染過程。默認返回 true,也就是說,只要組件觸發了更新,組件就一定會更新   */  shouldComponentUpdate (nextProps, nextState) {    return true  }
React.PureComponent純組件

這個是用于繼承 并不是生命周期(不需要開發者自己實現shouldComponentUpdate,就可以進行簡單的判斷來提升性能)

和React.Component相比 采用了props和state淺對比來實現shouldComponentUpdate 其他完全相同

存在問題(為什么PureComponent比較復雜的數據結構,可能會因深層的數據不一致而產生錯誤的否定判斷)

這個方法只對state和props進行了新舊地址值比較 而沒有深層對比其屬性的變化 修改地址值屬性不會導致頁面更新(JavaScript 中的對象一般是可變的(Mutable)因為使用了引用賦值 新的對象簡單的引用了原始對象 改變新的對象將影響到原始對象)

解決方法

避免修改原地址的屬性 采用新對象參數更新(使用 shallowCopy(淺拷貝)或 deepCopy(深拷貝)來避免被修改) 但這樣做造成了CPU和內存的浪費

componentWillUpdate

此生命周期函數將在React v17正式廢棄 使用componentWillReceiveProps代替

觸發時機

更新生命周期中重新渲染之前的最后一個方法 此時已經擁有了更新后的屬性和狀態 并且可以在這個方法中隨意處理這些數據

注意

此函數不會在初始化渲染時候被觸發禁止在這個函數中調用setState方法 會造成死循環
render(updating階段)

渲染函數 與mounting階段的render一致 用于渲染被React處理過的JSX到瀏覽器

getSnapshotBeforeUpdate

觸發時機

render渲染函數之前 state已更新

使用場景

獲取render之前的dom狀態

/**   *    * @param {*} prevProps 更新前的props   * @param {*} prevState 更新前的state   * @returns 返回值可以在componentDidUpdate中接收   */  getSnapshotBeforeUpdate (prevProps, prevState) {    return null  }
componentDidUpdate

觸發時機

組件每次重新渲染后觸發 不會在初始化渲染的時候觸發

注意

在此生命周期函數中使用setState 需要加if條件判斷 prevProps、prevState 和 this.state 之間的數據變化 用于跳出循環

/**   *    * @param {*} prevProps 更新前的props   * @param {*} prevState 更新前的state   * @param {*} snapshot getSnapshotBeforeUpdate傳過來的   */  componentDidUpdate (prevProps, prevState, snapshot) {  }
react v17刪除以下生命周期函數原因

componentWillReceiveProps | componentWillUpdate | componentWillReceiveProps

原因

被廢棄的三個函數都是在render之前,因為fiber的出現,很可能因為高優先級任務的出現而打斷現有任務導致它們會被執行多次

簡而言之就是React官方認為開發者會在這三個函數階段編寫副作用代碼(約束開發者)

卸載階段componentWillUnmount

觸發時機

在組件卸載之前觸發

使用場景

注銷事件監聽器取消網絡請求取消定時器解綁 DOM 事件
componentWillUnmount () {  }
捕獲錯誤static getDerivedStateFromError

觸發時機

該生命周期函數會在子孫組件拋出錯誤時執行

import React from "react";export default class GetDerivedStateFromError extends React.Component {    /**   *    * @param {*} error 錯誤信息   * @returns    * 它接收拋出的錯誤作為參數并且需要返回值用于更新 State   */  static getDerivedStateFromError(error) {    return   }  render () {    return (      
1
) }}
componentDidCatch

觸發時機

該生命周期函數會在子孫組件拋出錯誤時執行

使用方式和getDerivedStateFromError一致

錯誤邊界(Error Boundary)

一般情況下 任何組件在渲染期間發生錯誤 都會導致整個組件樹都被卸載

錯誤邊界是React的一個組件 這個組件可以捕獲發生在任何組件樹內錯誤 根據不同崩潰內容用頁面反饋

注意

錯誤邊界自身錯誤異步錯誤事件中錯誤服務器渲染錯誤
import React, { Component } from "react";export default class ErrorBoundary extends Component {  state = { hasError: false };  render() {    // 發生錯誤時 hasError 為 false 用頁面反饋    if (this.state.hasError) {      return 

發生錯誤

; } // 沒有發生錯誤 hasError 為 true 正常執行代碼 return this.props.children; } // componentDidCatch生命周期函數會在子孫組件拋出錯誤時執行 componentDidCatch(error, info) { this.setState({ hasError: true }); }}

標簽:

頭條精選