每個組件都有若干生命周期函數。如函數名稱所示,帶有will
前綴的函數會在某些動作發生前被調用,而帶有did
前綴的函數則在發生后被調用。
可以簡單的為組件的生命周期劃分為以下三個階段:
- 初始化階段(Mounting)
即組件實例被創建及被插入到Dom的階段。
以下函數會被調用:
constructor()
componentWillMount()
render()
componentDidMount()
- 掛載中階段(Updating)
此間主要對組件進行更新。更新可能是由props
或者state
的變化引起的。
更新時以下函數會被調用:
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
- 銷毀階段(Unmounting)
即組件要被刪除的階段。以下函數會被調用:
componentWillUnmount()
生命周期函數使用注意事項與時機
- render()
調用時檢查this.props
和this.state
,并返回React element(標準dom元素,如<div />
,或自定義復合組件,如<MyComponent />
)。當然,也可以返回null
或false
來告訴React你并不想render任何東西。
render()
函數需要是 pure 的,即它不修改組件的state并且不會直接與瀏覽器交互。如果你要和瀏覽器交互,推薦在componentDidMount()
或其他生命周期函數中操作。
shouldComponentUpdate()
函數返回false
時render()
不會被調用
constructor(props)
組件掛載前調用。因為每一個組件類都是React.Component
的派,重寫該函數一定記得在第一行就調用super(props)
,否則會因為沒有定義this.props
引起bug。
初始化state、綁定方法(如reflux的state mapping)等適合放在該函數中。如果需要這兩種操作就不用重寫該方法了。
基于props的初始化state同樣可以放在該方法中,注意是初始化state,后續的props變化不會再引起state變化,如果要將props的變化映射到state,需要在componentWillReceiveProps(nextProps)
中調用setState()
方法。componentWillMount()
組件被掛載前、render函數被調用前調用,因此,在其中同步地改變state不會引起re-render。
這是server rendering模式中唯一一個被調用的生命周期函數,不過通常建議優先使用constructor。componentDidMount()
組件掛載后調用,網絡請求(獲取數據)可以放在該函數中,setState 會引起re-rendercomponentWillReceiveProps(nextProps)
在接收到新的props前被調用。如果需要將props的改變映射到state上,建議將映射放在這個函數中。
需要注意的是,即使props沒有發生變化,該函數也可能被調用,所以使用setState將props映射到state時,最好比對下this.props
和nextProps
,否則可能會造成額外的re-render。
在mounting階段,該函數不會被調用。shouldComponentUpdate(nextProps, nextState)
用于props、state的改變是否要響應到到組件上,在接收到新的props、state后componentWillUpdate()
前調用。
返回true,引起re-render,反之則不。
返回false,不影響子組件因其內部state變化引起的re-render。
目前返回false時componentWillUpdate()
和componentDidUpdate()
將不會被調用。未來React可能會對此作出改變:返回false依然會引起re-render,”treatshouldComponentUpdate()
as a hint rather than a strict directive“。
默認也是大多數情況下,state的改變都要響應到組件上(即返回true,re-render )。
如果確定組件re-render頻繁造成了頁面卡頓,React提供了React.PureComponent
類。它包含一個自帶簡單比較props、state變化的該方法,可以繼承該類進行優化。當然,也可以自己比較變化指定更新。componentWillUpdate(nextProps, nextState)
在接收到新的props、state后,render函數前被調用。初始化階段不會調用。不能在函數中使用setState
方法。
可在此函數中完成更新操作的準備工作,如一些更新前的subscription通知。componentDidUpdate(prevProps, prevState)
更新后立即調用,同樣初始化階段不會被調用。
可用在此對比前后props和state變化,決定是否要發某些網絡請求。componentWillUnmount()
組件被卸載銷毀前調用。
在該函數中可以做一些清理操作,如unsubscribe、取消網絡請求等。setState(updater, [callback])
用于更新組件state,異步形式,可以理解為一種請求。
updater參數是一個包含了prevState和props的函數,該函數需要返回新的state,你不能在其中直接修改state,如:
// correct
(prevState, props) => {
return { counter: prevState.counter + props.step }
};
// error
(prevState, props) => {
this.state.counter = preState.counter + props.step;
// something else
};
- forceUpdate()
調用forceUpdate會跳過shouldComponentUpdate ()
,通常盡量避免使用該函數。