React元件生命週期詳解

飛翔荷蘭人發表於2018-05-25

React元件生命週期

constructor( ) 構造方法

constructor是ES6對類的預設方法,通過 new 命令生成物件例項時自動呼叫該方法。並且,該方法是類中必須有的,如果沒有顯示定義,則會預設新增空的constructor( )方法。當存在constructor的時候⚠️必須手動呼叫super方法。如果在constructor中想使用this關鍵字,就必須先呼叫super方法 MDN-super。 在constructor中如果要訪問this.props需要在super中傳入props。但是無論有沒有定義constructor,super是否傳入props引數,在react的其他生命週期中this.props都是可以使用的,這是React自動附帶的。

class MyClass extends React.component{
    constructor(props){
        super(props); // 宣告constructor時必須呼叫super方法
        console.log(this.props); // 可以正常訪問this.props
    }
}
複製程式碼

constructor 構造方法常用來初始化state

class MyClass extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            list: this.props.List
        };
        this.state.list = []; //修改state
        setTimeout(() => {
          this.setState({list: [1, 2, 3]}); //非同步操作後 setState 觸發渲染
        }, 100);
    }
}
複製程式碼

需要注意的是,在建構函式裡定義了state,當你想在一些操作後修改state,只需要直接操作this.state即可, 如果你在建構函式裡執行了非同步操作,就需要呼叫setState來觸發重新渲染。在其餘的地方當你需要改變state的時候只能使用this.setState,這樣 React 才會觸發重新整理UI渲染。

Class靜態方法例項屬性 初始化state

class ReactCounter extends React.Component {
	state = {
	  list: []
	};
}
複製程式碼

具體文章可見Class-的靜態方法

componentWillMount() 元件掛載之前

在元件掛載之前呼叫且全域性只呼叫一次。如果在這個鉤子裡可以setState,render後可以看到更新後的state,不會觸發重複渲染。該生命週期可以發起非同步請求,並setState。(React v16.3後廢棄該生命週期,可以在constructor中完成設定state

render()  渲染元件

render是一個React元件必須定義的生命週期,用來渲染dom。⚠️不要在render裡面修改state,會觸發死迴圈導致棧溢位。render必須返回reactDom

render() {
	const {nodeResultData: {res} = {}} = this.props;
	if (isEmpty(res)) return noDataInfo;
	const nodeResult = this.getNodeResult(res);
	return (
		<div className="workspace-dialog-result">
			{nodeResult}
		</div>
	);
複製程式碼

componentDidMount() 元件掛載完成後

在元件掛載完成後呼叫,且全域性只呼叫一次。可以在這裡使用refs,獲取真實dom元素。該鉤子內也可以發起非同步請求,並在非同步請求中可以進行setState。

componentDidMount() {
	axios.get('/auth/getTemplate').then(res => {
		const {TemplateList = []} = res;
		this.setState({TemplateList});
	});
}
複製程式碼

componentWillReceiveProps (nextProps ) props即將變化之前

props發生變化以及父元件重新渲染時都會觸發該生命週期,在該鉤子內可以通過引數nextProps獲取變化後的props引數,通過this.props訪問之前的props。該生命週期內可以進行setState。(React v16.3後廢棄該生命週期,可以用新的週期 static getDerivedStateFromProps 代替)

shouldComponentUpdate(nextProps, nextState) 是否重新渲染

元件掛載之後,每次呼叫setState後都會呼叫shouldComponentUpdate判斷是否需要重新渲染元件。預設返回true,需要重新render。返回false則不觸發渲染。在比較複雜的應用裡,有一些資料的改變並不影響介面展示,可以在這裡做判斷,優化渲染效率。

componentWillUpdate(nextProps, nextState)

shouldComponentUpdate返回true或者呼叫forceUpdate之後,componentWillUpdate會被呼叫。不能在該鉤子中setState,會觸發重複迴圈。(React v16.3後廢棄該生命週期,可以用新的週期 getSnapshotBeforeUpdate)

componentDidUpdate() 完成元件渲染

除了首次render之後呼叫componentDidMount,其它render結束之後都是呼叫componentDidUpdate。該鉤子內setState有可能會觸發重複渲染,需要自行判斷,否則會進入死迴圈。

componentDidUpdate() {
    if(condition) {
        this.setState({..}) // 設定state
    } else {
        // 不再設定state
    }
}
複製程式碼

componentWillUnmount() 元件即將被解除安裝

元件被解除安裝的時候呼叫。一般在componentDidMount裡面註冊的事件需要在這裡刪除。

生命週期圖

React元件生命週期詳解

完整的生命週期示例

class LifeCycle extends React.Component {
    constructor(props) {
        super(props);
        this.state = {str: "hello"};
    }

    componentWillMount() {
        alert("componentWillMount");
    }

    componentDidMount() {
        alert("componentDidMount");
    }

    componentWillReceiveProps(nextProps) {
        alert("componentWillReceiveProps");
    }

    shouldComponentUpdate() {
        alert("shouldComponentUpdate");
        return true;        // 記得要返回true
    }

    componentWillUpdate() {
        alert("componentWillUpdate");
    }

    componentDidUpdate() {
        alert("componentDidUpdate");
    }

    componentWillUnmount() {
        alert("componentWillUnmount");
    }
	render() {
        alert("render");
        return(
            <div>
                <span><h2>{parseInt(this.props.num)}</h2></span>
                <br />
                <span><h2>{this.state.str}</h2></span>
            </div>
        );
    }
}
複製程式碼

React v16.3 新加入的生命週期 (轉載)

react v16.3刪掉以下三個生命週期

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

新增兩個生命週期

  • static getDerivedStateFromProps
  • getSnapshotBeforeUpdate

static getDerivedStateFromProps

  • 觸發時間:在元件構建之後(虛擬dom之後,實際dom掛載之前) ,以及每次獲取新的props之後。
  • 每次接收新的props之後都會返回一個物件作為新的state,返回null則說明不需要更新state.
  • 配合componentDidUpdate,可以覆蓋componentWillReceiveProps的所有用法
class Example extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
    // 沒錯,這是一個static
  }
}
複製程式碼

getSnapshotBeforeUpdate

  • 觸發時間: update發生的時候,在render之後,在元件dom渲染之前。
  • 返回一個值,作為componentDidUpdate的第三個引數。
  • 配合componentDidUpdate, 可以覆蓋componentWillUpdate的所有用法。
class Example extends React.Component {
	getSnapshotBeforeUpdate(prevProps, prevState) {
	// ...
	}
}
複製程式碼

相關文章