React v16.4 的生命週期圖服務器
React v16.4 的生命週期async
原來(React v16.0前)的生命週期在React v16推出的Fiber以後就不合適了,由於若是要開啓async rendering,在render函數以前的全部函數,都有可能被執行屢次。函數
原來(React v16.0前)的生命週期有哪些是在render前執行的呢?this
若是開發者開了async rendering,並且又在以上這些render前執行的生命週期方法作AJAX請求的話,那AJAX將被無謂地屢次調用。。。明顯不是咱們指望的結果。並且在componentWillMount裏發起AJAX,無論多快獲得結果也趕不上首次render,並且componentWillMount在服務器端渲染也會被調用到(固然,也許這是預期的結果),這樣的IO操做放在componentDidMount裏更合適。code
禁止不能用比勸導開發者不要這樣用的效果更好,因此除了shouldComponentUpdate,其餘在render函數以前的全部函數(componentWillMount,componentWillReceiveProps,componentWillUpdate)都被getDerivedStateFromProps替代。component
也就是用一個靜態函數getDerivedStateFromProps來取代被deprecate的幾個生命週期函數,就是強制開發者在render以前只作無反作用的操做,並且能作的操做侷限在根據props和state決定新的state對象
React v16.0剛推出的時候,是增長了一個componentDidCatch生命週期函數,這只是一個增量式修改,徹底不影響原有生命週期函數;可是,到了React v16.3,大改動來了,引入了兩個新的生命週期函數。生命週期
getDerivedStateFromProps
,getSnapshotBeforeUpdate
getDerivedStateFromProps
原本(React v16.3中)是隻在建立和更新(由父組件引起部分),若是不是由父組件引起,那麼getDerivedStateFromProps也不會被調用,如自身setState引起或者forceUpdate引起。開發
React v16.3 的生命週期圖get
React v16.3
這樣的話理解起來有點亂,在React v16.4中改正了這一點,讓getDerivedStateFromProps不管是Mounting仍是Updating,也不管是由於什麼引發的Updating,所有都會被調用,具體可看React v16.4 的生命週期圖。
React v16.4後的getDerivedStateFromProps
static getDerivedStateFromProps(props, state) 在組件建立時和更新時的render方法以前調用,它應該返回一個對象來更新狀態,或者返回null來不更新任何內容。
getSnapshotBeforeUpdate() 被調用於render以後,能夠讀取但沒法使用DOM。它使您的組件能夠在可能更改以前從DOM捕獲一些信息(例如滾動位置)。今生命週期返回的任何值都將做爲參數傳遞給componentDidUpdate()。
官網給的例子:
class ScrollingList extends React.Component { constructor(props) { super(props); this.listRef = React.createRef(); } getSnapshotBeforeUpdate(prevProps, prevState) { //咱們是否要添加新的 items 到列表? // 捕捉滾動位置,以便咱們能夠稍後調整滾動. if (prevProps.list.length < this.props.list.length) { const list = this.listRef.current; return list.scrollHeight - list.scrollTop; } return null; } componentDidUpdate(prevProps, prevState, snapshot) { //若是咱們有snapshot值, 咱們已經添加了 新的items. // 調整滾動以致於這些新的items 不會將舊items推出視圖。 // (這邊的snapshot是 getSnapshotBeforeUpdate方法的返回值) if (snapshot !== null) { const list = this.listRef.current; list.scrollTop = list.scrollHeight - snapshot; } } render() { return ( <div ref={this.listRef}>{/* ...contents... */}</div> ); }