iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 6
2
Modern Web

寫React的那些事系列 第 6

React Day6 - Life Cycle 生命週期

  • 分享至 

  • twitterImage
  •  

我們自己定義的component都是繼承React.Component而來,component會根據props與state的改變來render畫面,而除了component裡面一定要有的render method,React.Component還有一些其他內建的method,今天要介紹的就是這些內建method,以及這些method在component裡的生命週期。

Life Cycle


Component method分成三種跟生命週期有關的描述:

  • Mounting:當component的instance被建立,並且顯示在DOM上。
  • Updating:當props或是state改變時,重新渲染DOM(re-render)。
  • Unmounting:當component將要從DOM被移除的時候。

Mounting Method


redner()

它的執行時間點,就是當每次props或是state被改變時,就會被執行一次。

繼承React.Component的所有method裡面唯一必須要寫的方法,並且要回傳一個React element,這個element可以是前面幾天我們提到的HTML tag component或是User-defined component。回傳的element要有一個根元件包覆。

如果某種判斷式情況下,需要不回傳任何element,可以回傳null或是false,來表示不顯示任何東西。

「The render function should be pure」,這是使用render很重要的一件事情,意思就是說要保持render的乾淨,不能在裡面使用setState,也就是不在render()中修改state,或是和瀏覽器互動,因為它只會在當下執行一次,若是在這邊調用任何改變畫面的操作,都會讓顯示不正確,也讓component顯得複雜難懂。

constructor(props)

這個方法會在component還沒有被mount到畫面上,就先執行一次,也就是建構子。

如果要在自訂的component使用這個方法,必須在第一行先執行super(props),不然的話之後會找不到this.props。如果沒用到props,也可以偷懶只寫super()。

初始化state和使用bind指定this也是在這個方法裡面,如果state會根據props來設定,也可以在初始化state的時候直接使用props。

constructor(props) {
	super(props);
	this.state = {
		color: props.initialColor
	};
}

componentWillMount()

Component將要被mount在畫面上時,會執行這個方法,會發生在第一次render()之前,也因為在會在render()之前,所以在這邊設定任何state也就不會觸發rerender,必須避免執行setState,初始化state放在constructor()是比較好的做法。

componentDidMount()

會在component被mount在畫面上後執行,所以在這邊也很適合做跟DOM有關的初始化操作,例如:執行i18n的localize,或是AJAX後端的API,或是window.addEventListener...等。

Updating Method


componentWillReceiveProps(nextProps)

這方法會在父元件更新props後執行,它會接收新的props(nextProps)當參數,如果state會根據props有所改變,那麼在update props的時候,也可以在這個方法裡做setState。

這個方法有可能在props沒有改變的時候被觸發,因為父元件有可能重新re-render這個component導致,所以在setState的時候,可以先比較一下this.props和nextProps,避免不必要的re-render。

componentWillReceiveProps(nextProps) {
	if (this.props.initialColor !=== nextProps.initialColor) {
		this.setState = ({
			color: props.initialColor
		});
	}
}

shouldComponentUpdate(nextProps, nextState)

這個方法會在接收到新的props和state之後,在觸發re-render之前,會return是否要re-render畫面的boolean,預設是return true。它不會在第一次render(),或是forceUpdate()的時候被執行。如果return false,表示不重繪畫面,那後面的componentWillUpdate()、 render()、componentDidUpdate()也不會被執行。

通常不希望畫面re-render的時候,可以比較目前props與next props,目前state與next state,確定真的有值不同才return true,如果沒有不同則return false。

一般來說是在調教效能的時候使用,因為不希望畫面做不必要的re-render,React也提供React.PureComponent,來幫忙判斷shouldComponentUpdate比對的結果,也建議使用React.PureComponent來提升整體效能。不過,要特別注意的是,因為props和state可能會是object和array型態,React.PureComponent只提供shallow comparison。

componentWillUpdate(nextProps, nextState)

當接收到新的props和state時,re-render之前會執行這個方法,但如果shouldComponentUpdate回傳false,則不會執行。

在這個方法裡面,不可以做setState,因為這樣會導致state錯亂,如果有根據props設定的state,就像前面提到的,需要在componentWillReceiveProps使用。

componentDidUpdate(prevProps, prevState)

看完前面的一些方法命名的方式,應該會覺得這個就很好懂了吧!它會在component被update之後執行,不過同樣的,它在第一次render()完之後也不會觸發,只有"upate"後才會。在這邊可以重新執行根據props或是state更新後,DOM需要改變的變化,例如:重新執行i18n的localize,或是AJAX後端的API...等

Unmounting Method


componentWillUnmount()

當component將要從DOM被移除前,會執行這個方法。

當component裡面有做setInterval,或是addEventListener...等,在componentDidMount()裡面做的設定,若需要被終止、移除、清理,就需要在這個方法中執行,例如clearInterval、removeEventListener...等。

Other APIs


React.Component跟生命週期比較沒有關係的,還有兩個方法:

this.setState(nextState, callback)

這是用來更新state的方法,第一個參數表示要更新的state,不需要把所有state都列舉在裡面,只要設定要更新的state就好。

this.setState({ mykey: 'my new value' });

第一個參數也可以用一個會return新的state的function傳入,function(state, props) => newState,這邊直接使用ES6 Arrow function,通常是要根據目前props設定的state會用到這樣的方式。

this.setState((prevState, props) => {
	return {myInteger: prevState.myInteger + props.step};
});

第二個參數傳入當state被更新且完成re-render後要執行的callback,通常建議callback希望執行的動作寫在componentDidUpdate()裡比較好。

component.forceUpdate(callback)

通常Component會依據props和state來決定re-render,但如果這個component有依賴其他的data來做render,可以使用這個方法update UI,它會跳過前面說的shouldComponentUpdate()直接執行re-render。

不過,一般來說建議避免使用forceUpdate,盡量讓component貼近React設計的方式,用props和state來管理UI,讓它越pure越好。

Recap


  • 內建Life Cycle裡的方法, this 都指向component本身,若是自訂新增的方法,則需使用bind指定this,或是Arrow function讓this自動綁定。

  • 第一次render流程:

    • constructor(props)
    • componentWillMount()
    • redner()
    • componentDidMount()
  • Update流程:

    • componentWillReceiveProps(nextProps)
    • shouldComponentUpdate(nextProps, nextState) // 若是return false,則停在這邊
    • componentWillUpdate(nextProps, nextState)
    • redner()
    • componentDidUpdate(prevProps, prevState)
  • 不可以使用setState的方法:

    • render
    • componentWillMount // 不會觸發re-render
    • shouldComponentUpdate
    • componentWillUpdate

參考


React官網 React.Component


上一篇
React Day5 - state 與 setState
下一篇
React Day7 - NPM
系列文
寫React的那些事31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言