天天看點

react17 生命周期場景解釋

一、廢除的生命周期

官網文檔指出使用這些生命周期的代碼會在未來版本的react中更容易産生bug,尤其是對于異步渲染的版本

由于未來采用異步渲染機制,是以即将在17版本中去掉的生命周期鈎子函數

componentWillMount

componentWillRecieveProps

componentWIllUpdate

二、新增的生命周期

static getDerivedStateFromProps(nextProps, prevState) {}

用于替換componentWillReceiveProps,可以用來控制 props 更新 state 的過程;它傳回一個對象表示新的 state;如果不需要更新,傳回 null 即可

在每次渲染之前都會調用,不管初始挂載還是後面的更新都會調用,這一點和componentWillReceiveProps不同(隻有當父元件造成重新渲染時才調用

簡單的了解就說從props中擷取state,這個生命周期的功能實際上就是将傳入的props映射到state上面

getDerivedStateFromProps是一個靜态函數,也就是這個函數不能通過this通路到class的屬性,也并不推薦直接通路屬性。而是應該通過參數提供的nextProps以及prevState來進行判斷,根據新傳入的props來映射到state

如果props傳入的内容不需要影響到你的state,那麼就需要傳回一個null,這個傳回值是必須的,是以盡量将其寫到函數的末尾

getSnapshotBeforeUpdate() {}

在最近的更改被送出到DOM元素前,使得元件可以在更改之前獲得目前值,此生命周期傳回的任意值都會傳給componentDidUpdate()。

用于替換 componentWillUpdate,該函數會在update後 DOM 更新前被調用,用于讀取最新的 DOM 資料,傳回值将作為 componentDidUpdate 的第三個參數

在最新的渲染資料送出給DOM前會立即調用,它讓你在元件的資料可能要改變之前擷取他們

componendDidCatch(error, info)

如果一個元件定義了componentDidCatch生命周期,則他将成為一個錯誤邊界(錯誤邊界會捕捉渲染期間、在生命周期方法中和在它們之下整棵樹的構造函數中的錯誤,

就像使用了try catch,不會将錯誤直接抛出了,保證應用的可用性)

三、下面來看看實際應用場景分析:

/*
 * @Descripttion: react17 生命周期測試
 * @version: 
 * @Author: lhl
 * @Date: 2021-03-04 14:51:12
 * @LastEditors: lhl
 * @LastEditTime: 2021-03-26 18:46:49
 */
import React, { Component } from 'react'
import PropTypes from 'prop-types' // prop代表父元件傳遞過來的值,types代表類型 簡單來說就是用來校驗父元件傳遞過來值的類型


// 類元件 
/*
    1.挂載時順序
    constructor() --> static getDerivedStateFromProps(props, state) --> render() --> componentDidMount()

    2.更新時順序
    static getDerivedStateFromProps(props, state) --> shouldComponentUpdate() --> render() --> 
    static getSnapshotBeforeUpdate(prevProps, prevState) --> componentDidUpdate()

    3.解除安裝 (比如頁面切換)
    componentWillUnmount()

    在 Fiber 機制下,render 階段是允許暫停、終止和重新開機的。廢棄的生命周期鈎子函數,它們都處于render階段,都可能被重複執行
    在 componentWillReceiveProps 和 componentWillUpdate 裡濫用 setState 導緻重複渲染死循環的
    forceUpdate(callback) - 元件強制更新,會跳過shouldComponentUpdate
*/
export default class LifeCycle extends Component {
    // constructor()用來做一些元件的初始化工作,如定義this.state的初始内容 為事件處理函數綁定執行個體
    constructor(props){
        // super(props)用來調用基類的構造方法( constructor() ), 也将父元件的props注入給子元件,供子元件讀取(元件中props隻讀不可變,state可變)
        super(props)
        this.state = {
            count: 0
        }
        console.log('constructor')
    }
    // static propTypes = {
    //     prop: PropTypes // react裡的defaultProps來設定預設的props值
    // }

    static getDerivedStateFromProps(props, state){
        console.log(props, state,'getDerivedStateFromProps')
        return true
    }

    componentDidMount(){
        console.log('componentDidMount')
    }

    // 根據更新後的state或props判斷是否重新渲染DOM,傳回值為布爾值,常用來性能優化
    /**
     * 判斷是否需要更新視圖,執行後面的render方法
     * 1. 如果傳回 false ,則不需要執行後面的render方法,視圖也不會改變
     * 2. 傳回true, 需要執行render方法,視圖也會對應的改變
     */
    // 下一個和目前狀态對比 nextState === this.state.xxx 沒有變化就 return false 否則 true
    shouldComponentUpdate(nextProps, nextState){
        console.log(nextProps, nextState, 'shouldComponentUpdate')
        return true
    }
    
    // 該函數會在update後 DOM 更新前被調用,用于讀取最新的 DOM 資料,傳回值将作為 componentDidUpdate 的第三個參數
    getSnapshotBeforeUpdate(prevProps, prevState){
        console.log(prevProps, prevState,'getSnapshotBeforeUpdate')
        return true
    }

    // state或props更新後調用
    componentDidUpdate(props, state, snapshot){
        console.log(props, state, snapshot,'componentDidUpdate')
    }

    // 元件銷毀或解除安裝時調用
    componentWillUnmount(){
        console.log('componentWillUnmount')
    }

    // 錯誤處理
    // 後代元件跑出錯誤時調用,并傳回一個值以更新state
    static getDerivedStateFromError(callback){
        console.log(callback)
    }
    
    // 後代元件抛出錯誤後調用,參數info包含有關元件錯誤的棧資訊
    componentDidCatch(error, info){
        console.log(error, info)
    }

    handleChange = () => {
        this.setState({
            count: 12
        })
    }

    // 渲染React元件  PureComponet 和 shouldComponentUpdate 處理渲染性能優化問題
    // 初始化
    // setState()在任何情況下都會導緻元件的重新渲染,即使state未發生變化
    // 隻要父元件重新渲染了,那麼子元件就會重新渲染
    render() {
        console.log('render')
        const { count } = this.state
        return (
            <div>
                <h1>react 17 生命周期</h1>
                <button onClick={this.handleChange}>更改狀态{count}</button>
            </div>
        )
    }
}

LifeCycle.propTypes = {
    name: PropTypes.string
};