在 React 16.3 中,Facebook 的工程師們給 React 帶來一系列的新的特性,如 suspense 和 time slicing 等,這些都爲 React 接下來即將到來的異步渲染機制作準備,有興趣的能夠看 Sophie Alpert 在 JSConf Iceland 2018 的演講。javascript
像 time slicing 等 React 內部優化特性,在 API 層面不會有太大變化,而 API 層面最大的變化,應該在生命週期鉤子。html
React 的生命週期 API 一直以來十分穩定,可是當 React 團隊在引入異步渲染機制的時候,發現以前的生命週期會的使用產生一些問題,因此纔會改動生命週期 API,感興趣的能夠看這篇博客。java
在 React 16.3 中,爲下面三個生命週期鉤子加上了 UNSAFE 標記:react
新增了下面兩個生命週期方法:git
在目前16.X(X>3)的 React 中,使用 componentWillMount, componentWillReceiveProps, and componentWillUpdate 這三個方法會收到警告。React 團隊計劃在 17.0 中測地廢棄掉這幾個 API。github
class Example extends React.Component {
static getDerivedStateFromProps(props, state) {
// ...
}
}
複製代碼
React 在實例化組件以後以及從新渲染組件以前,將調用新的靜態 getDerivedStateFromProps 生命週期方法。該方法相似於 componentWillReceiveProps,能夠用來控制 props 更新 state 的過程。它返回一個對象表示新的 state。若是不須要更新組件,返回 null 便可。網絡
getDerivedStateFromProps 與 componentDidUpdate一塊兒將會替換掉全部的 componentWillReceiveProps。less
class Example extends React.Component {
getSnapshotBeforeUpdate(prevProps, prevState) {
// ...
}
}
複製代碼
getSnapshotBeforeUpdate 方法在 React 對視圖作出實際改動(如 DOM 更新)發生前被調用,返回值將做爲 componentDidUpdate 的第三個參數。異步
getSnapshotBeforeUpdate 配合 componentDidUpdate 能夠取代 componentWillUpdate。async
由於在 React 將來的版本中,異步渲染機制可能會致使單個組件實例能夠屢次調用該方法。不少開發者目前會將事件綁定、異步請求等寫在 componentWillMount 中,一旦異步渲染時 componentWillMount 被屢次調用,將會致使:
如今,React 推薦將本來在 componentWillMount 中的網絡請求移到 componentDidMount 中。至於這樣會不會致使請求被延遲發出影響用戶體驗,React 團隊是這麼解釋的:
There is a common misconception that fetching in componentWillMount lets you avoid the first empty rendering state. In practice this was never true because React has always executed render immediately after componentWillMount. If the data is not available by the time componentWillMount fires, the first render will still show a loading state regardless of where you initiate the fetch. This is why moving the fetch to componentDidMount has no perceptible effect in the vast majority of cases.
componentWillMount、render 和 componentDidMount 方法雖然存在調用前後順序,但在大多數狀況下,幾乎都是在很短的時間內前後執行完畢,幾乎不會對用戶體驗產生影響。
大多數開發者使用 componentWillUpdate 的場景是配合 componentDidUpdate,分別獲取 rerender 先後的視圖狀態,進行必要的處理。但隨着 React 新的 suspense、time slicing、異步渲染等機制的到來,render 過程能夠被分割成屢次完成,還能夠被暫停甚至回溯,這致使 componentWillUpdate 和 componentDidUpdate 執行先後可能會間隔很長時間,足夠使用戶進行交互操做更改當前組件的狀態,這樣可能會致使難以追蹤的 BUG。
React 新增的 getSnapshotBeforeUpdate 方法就是爲了解決上述問題,由於 getSnapshotBeforeUpdate 方法是在 componentWillUpdate 後(若是存在的話),在 React 真正更改 DOM 前調用的,它獲取到組件狀態信息更加可靠。
除此以外,getSnapshotBeforeUpdate 還有一個十分明顯的好處:它調用的結果會做爲第三個參數傳入 componentDidUpdate,避免了 componentWillUpdate 和 componentDidUpdate 配合使用時將組件臨時的狀態數據存在組件實例上浪費內存,getSnapshotBeforeUpdate 返回的數據在 componentDidUpdate 中用完即被銷燬,效率更高。
React 近來 API 變化十分大,React 團隊很長時間以來一直在實現異步渲染機制,目前的特性只是爲異步渲染作準備,預計 React 在 17 版本發佈時,性能會取得巨大的提高,期待中。。。
PS:從 Sophie Alpert 演示的兩個 DEMO 上看,異步渲染的高效確實十分驚豔,有興趣的能夠看文章開頭的演講。
個人全部文章都彙總在個人 GitHub: HuQingyang (胡青楊) · GitHub ,歡迎關注、交流、拍磚、搞基。