一、廢除的生命周期
官網文檔指出使用這些生命周期的代碼會在未來版本的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
};