這是一個不錯的文章 (The (new) React lifecycle methods in plain, approachable language)[blog.logrocket.com/the-new-rea…] 作者: Ohans Emmanuel
下面一個生命週期說明的元件
import * as React from 'react';
interface lifeCycleState {
update: boolean,
pointer: number,
list: number[]
}
class LifeCycle extends React.Component<any, lifeCycleState> {
/**
* 從props中獲取派生state
* 在初始掛載時將元件呈現給DOM之前,會呼叫此方法。
* 本質上,這個方法允許元件根據props的變化更新其內部狀態
*
* @param nextProps
* @param prevState
*
* @return {Partial<S> | null}
*/
static getDerivedStateFromProps(nextProps: Readonly<any>, prevState: any) {
console.log('getDerivedStateFromProps', 'props= ', nextProps, ' state= ', prevState)
return {
// 不推薦使用這種方法。只是一個例子。無條件覆蓋狀態通常被認為是一個壞主意。
pointer: 1000
}
}
/**
* 從Error中獲取派生state
*
* @param error
*
* @return {Partial<S> | null}
*/
static getDerivedStateFromError (error: any) {
console.error('getDerivedStateFromError', error)
return null
}
constructor (props: any) { // 建構函式
super(props);
console.log('constructor')
this.state = {
update: false,
pointer: 10,
list: []
}
}
/**
* 在掛載之前立即呼叫,並在"Component#render"之前呼叫。
* 避免在此方法中引入任何副作用或訂閱。
* 注意:存在getSnapshotBeforeUpdate或getDerivedStateFromProps防止這被呼叫。
*
* @deprecated 16.3, 改用componentDidMount或constructor;在react 17中將停止工作
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#initializing-state
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path
*/
// componentWillMount () {
// console.log('componentWillMount')
// }
/**
*
* 在掛載之前立即呼叫,並在"Component#render"之前呼叫。
* 避免在此方法中引入任何副作用或訂閱。
*
* 此方法不會在React 17中停止工作。
*
* 注意:存在getSnapshotBeforeUpdate或getDerivedStateFromProps防止這被呼叫。
*
* @deprecated 16.3, 改用componentDidMount或constructor
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#initializing-state
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path
*/
// UNSAFE_componentWillMount () {
// console.log("UNSAFE_componentWillMount");
// }
/**
* 掛載元件後立即呼叫。在此處設定state將觸發重新渲染。
*/
componentDidMount () {
console.log('componentDidMount')
}
/**
* 當元件可能正在接收新的props時呼叫。
* 即使props沒有改變,React也可以呼叫它,所以一定要比較新的和現有的props,如果你只想處理變化。
* 呼叫`Component#setState`通常不會觸發此方法。
*
* 注意:存在getSnapshotBeforeUpdate或getDerivedStateFromProps防止這被呼叫。
*
* @param nextProps
* @param nextContext
*
* @deprecated 16.3, 使用 static getDerivedStateFromProps 代替; 在react 17中將停止工作
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path
*/
// componentWillReceiveProps (nextProps: Readonly<any>, nextContext: any) {
// console.log('componentWillReceiveProps ', nextProps);
// }
/**
* 當元件可能正在接收新的props時呼叫。
* 即使props沒有改變,React也可以呼叫它,所以一定要比較新的和現有的props,如果你只想處理變化。
* 呼叫`Component#setState`通常不會觸發此方法。
*
* 此方法不會在React 17中停止工作。
*
* 注意:存在getSnapshotBeforeUpdate或getDerivedStateFromProps防止這被呼叫。
*
* @param nextProps
* @param nextContext
*
* @deprecated 16.3, 使用 static getDerivedStateFromProps 代替
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path
*/
// UNSAFE_componentWillReceiveProps (nextProps: Readonly<any>, nextContext: any) {
// console.log('UNSAFE_componentWillReceiveProps ', nextProps);
// }
/**
* 在收到新的props或state時,在渲染之前立即呼叫。
* 初始渲染時不被呼叫。
*
* 注意:你不能在這裡呼叫`Component#setState`。
* 注意:存在getSnapshotBeforeUpdate或getDerivedStateFromProps防止這被呼叫。
*
* @param nextProps
* @param nextState
* @param nextContext
*
* @deprecated 16.3, 使用 getSnapshotBeforeUpdate 代替; 在react 17中將停止工作
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#reading-dom-properties-before-an-update
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path
*/
// componentWillUpdate(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any) {
// console.log('componentWillUpdate', nextProps, nextState, nextContext);
// }
/**
* 在收到新的props或state時,在渲染之前立即呼叫。
* 初始渲染時不被呼叫。
*
* 注意:你不能在這裡呼叫`Component#setState`。
*
* 此方法不會在React 17中停止工作。
*
* 注意:存在getSnapshotBeforeUpdate或getDerivedStateFromProps防止這被呼叫。
*
* @param nextProps
* @param nextState
* @param nextContext
*
* @deprecated 16.3, 使用 getSnapshotBeforeUpdate 代替
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#reading-dom-properties-before-an-update
* @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path
*/
// UNSAFE_componentWillUpdate(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any) {
// console.log('UNSAFE_componentWillUpdate');
// }
/**
* 呼叫以確定props和state的更改是否應觸發重新渲染。
* `Component`總是返回true。
* `PureComponent`在props和state上實現淺層比較,如果props或state已經改變則返回true
* 如果返回false,則為"Component#render","componentWillUpdate"並且不會呼叫`componentDidUpdate`。
*
* @param nextProps
* @param nextState
* @param nextContext
*
* @return {boolean} 控制元件是否更新 true更新 false不更新
*/
shouldComponentUpdate (nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any) {
console.log('shouldComponentUpdate', nextProps, nextState, nextContext);
return true
}
/**
* 在react將"render"的結果應用於document之前執行,以及
* 返回要提供給ComponentDidUpdate的物件。對儲存有用
* "render"之前的滾動位置等操作會導致對其進行更改。
*
* 注意:getSnapshotBeforeUpdate的存在可防止生命週期事件。
*
* 這個生命週期和 `componentWillMount`、`UNSAFE_componentWillMount`、
* `componentWillReceiveProps`、`UNSAFE_componentWillReceiveProps`、
* `componentWillUpdate`和`UNSAFE_componentWillUpdate` 不能共存 否則報警告
*
* @param prevProps 前屬性
* @param prevState 前狀態
*
* @return {SS | null}
*/
getSnapshotBeforeUpdate(prevProps: Readonly<any>, prevState: Readonly<any>) {
console.log('getSnapshotBeforeUpdate ', 'prevProps= ', prevProps, ' prevState= ', prevState);
return null
}
/**
* 更新發生後立即呼叫。
* 初始渲染時不被呼叫。
* 僅當存在getSnapshotBeforeUpdate且返回非null時,才會顯示snapshot(getSnapshotBeforeUpdate的返回值)。
*
* @param prevProps 前屬性
* @param prevState 前狀態
* @param snapshot getSnapshotBeforeUpdate的返回值
*/
componentDidUpdate (prevProps: Readonly<any>, prevState: Readonly<any>, snapshot?: any) { // 元件更新完成
console.log('componentDidUpdate', snapshot);
}
/**
* 捕獲後代元件中生成的異常。
* 未處理的異常將導致要解除安裝的整個元件樹。
*
* @param error
* @param errorInfo
*/
componentDidCatch (error: Error, errorInfo: React.ErrorInfo) {
console.error('componentDidCatch error', error)
console.error('componentDidCatch errorInfo', errorInfo)
}
/**
* 在元件被銷燬之前立即呼叫。
* 在此方法中執行任何必要的清理,例如取消了網路請求,或清理了`componentDidMount`中建立的任何DOM元素。
*/
componentWillUnmount () {
console.log('componentWillUnmount')
}
handleClick = () => {
this.setState({
update: !this.state.update
})
}
handleThrowError = () => {
// throw new Error('手動丟擲錯誤!')
const {list} = this.state;
list.push(12)
this.setState({
list
})
}
render () { // 渲染元件
console.log('component render')
return (
<div className='lifecycle'>
lifecycle render {this.state.update? 'true' : 'false'}
<button onClick={this.handleClick}>
click me
</button>
<img src="https://pic2.zhimg.com/v2-610ad32e1ed334b3b12026a845e83399_r.jpg" />
<div>pointer: {this.state.pointer}</div>
<button onClick={this.handleThrowError}>點選5次</button>
<div>
<ul>
{
this.state.list.map((l: number, i: number) => {
if (this.state.list.length === 5) {
throw new Error('出錯了!')
}
return <li key={i}>{l}</li>
})
}
</ul>
</div>
</div>
)
}
}
export default LifeCycle
複製程式碼