react 舊版生命周期
React 的生命周期圖如上所示,主要可分為 初始化階段、掛載階段、更新階段、卸載階段。
初始化階段
發生在 constructor 中的內容,在 constructor 中進行 state、props 的初始化,在這個階段修改 state,不會執行更新階段的生命周期,可以直接對 state 賦值。
掛載階段
對應的生命周期為:
* 1.componentWillMount 發生在 render 函數之前,還沒有掛載 Dom * 2.render * 3.componentDidMount 發生在 render 函數之后,已經掛載 Dom
更新階段
更新階段分為由 state 更新引起和 props 更新引起
* props
* 1. componentWillReceiveProps(nextProps,nextState) 這個生命周期主要為我們提供對 props 發生改變的監聽,如果你需要在 props 發生改變后,相應改變組件的一些 state。在這個方法中改變 state 不會二次渲染,而是直接合並 state。 * 2. shouldComponentUpdate(nextProps,nextState) 這個生命周期需要返回一個 Boolean 類型的值,判斷是否需要更新渲染組件,優化 react 應用的主要手段之一,當返回 false 就不會再向下執行生命周期了,在這個階段不可以 setState(),會導致循環調用。 * 3. componentWillUpdate(nextProps,nextState) 這個生命周期主要是給我們一個時機能夠處理一些在 Dom 發生更新之前的事情,如獲得 Dom 更新前某些元素的坐標、大小等,在這個階段不可以 setState(),會導致循環調用。 **一直到這里 this.props 和 this.state 都還未發生更新** * 4. render 執行 render 函數。 * 5. componentDidUpdate(prevProps, prevState) 在此時已經完成渲染,Dom 已經發生變化,State 已經發生更新,prevProps、prevState 均為上一個狀態的值。 * state(具體同上) * 1. shouldComponentUpdate * 2. componentWillUpdate * 3. render * 4. componentDidUpdate
卸載階段
對應的生命周期為
* componentWillUnmount
componentWillUnmount 會在組件卸載及銷毀之前直接調用。在此方法中執行必要的清理操作,例如,清除 timer,取消網絡請求或清除在 componentDidMount 中創建的訂閱等。componentWillUnmount 中不應調用 setState,因為該組件將永遠不會重新渲染。組件實例卸載后,將永遠不會再掛載它。
根據上面的生命周期可以理解所謂的 setState 是“異步”的並非 setState 函數插入了新的宏任務或微任務,而是在進行到 componentDidUpdate 這個生命周期之前,React 都不會更新組件實例的 state 值。
引發問題: setState 在 setTimeout 和其他事件回調中卻可以同步更新( this.state 立即獲得更新結果)是為什么呢?
答案: 在 React 中,如果是由 React 引發的事件處理(比如:onClick 引發的事件處理),調用 setState 不會同步更新 this.state,除此之外的 setState 調用會同步執行this.setState。 “除此之外”指的是:繞過 React 通過 addEventListener 直接添加的事件處理函數和 setTimeout/setInterval 產生的異步調用。
解釋: 每次 setState 產生新的state會依次被存入一個隊列,然后會根據isBathingUpdates 變量判斷是直接更新 this.state 還是放進 dirtyComponent 里回頭再說。isBatchingUpdates 默認是 false,也就表示 setState 會同步更新 this.state。但是,當 React 在調用事件處理函數之前就會調用 batchedUpdates,這個函數會把 isBatchingUpdates 修改為 true,造成的后果就是由 React 控制的事件處理過程 setState 不會同步更新 this.state。
解決方法: 當我們想要依據上一個 state 的值來 setState 時,可以使用函數式 setState。
function increment(state, props) { return {count: state.count + 1}; } function incrementMultiple() { this.setState(increment); this.setState(increment); this.setState(increment); }
React 新版生命周期
React 16 中刪除了如下三個生命周期。
componentWillMount
componentWillReceiveProps
componentWillUpdate
官方給出的解釋是 react 打算在17版本推出新的 Async Rendering,提出一種可被打斷的生命周期,而可以被打斷的階段正是實際 dom 掛載之前的虛擬 dom 構建階段,也就是要被去掉的三個生命周期。
本身這三個生命周期所表達的含義是沒有問題的,但 react 官方認為我們(開發者)也許在這三個函數中編寫了有副作用的代碼,所以要替換掉這三個生命周期,因為這三個生命周期可能在一次 render 中被反復調用多次。
取代這三個生命周期的是兩個新生命周期
電腦刺綉綉花廠 http://www.szhdn.com 廣州品牌設計公司https://www.houdianzi.com
static getDerivedStateFromProps(nextProps,nextState)
在 React 16.3.0 版本中:在組件實例化、接收到新的 props 時會被調用
在 React 16.4.0 版本中:在組件實例化、接收到新的 props 、組件狀態更新時會被調用
該方法可以返回一個對象,將會和 state 發生合並,且不會觸發 re-render。
這個生命周期主要為我們提供了一個可以在組件實例化或 props、state 發生變化后根據 props 修改 state 的一個時機,用來替代舊的生命周期中的 componentWillMount、ComponentWillReceiveProps。因為是一個靜態方法,this 指向不是組件實例。
getSnapshotBeforeUpdate(prevProps,prevState)
在 render 函數調用之后,實際的 Dom 渲染之前,在這個階段我們可以拿到上一個狀態 Dom 元素的坐標、大小的等相關信息。用於替代舊的生命周期中的 componentWillUpdate。
該函數的返回值將會作為 componentDidUpdate 的第三個參數出現。