日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

本篇文章帶大家看看React新版生命周期帶來了哪些變化。

React16.4版本之后使用了新的生命周期,它使用了一些新的生命周期鉤子(getDerivedStateFromProps、getSnapshotBeforeUpdate),并且即將廢棄老版的3個生命周期鉤子(componentWillMount、componentWillReceiveProps、componentWillUpdate)。

一、新版生命周期

如圖所示,我們可以看到,在組件第一次掛載時會經歷:

構造器(constructor)=》修改state屬性(getDerivedStateFromProps)=》組件掛載渲染(render)=》組件掛載完成(componentDidMount)

組件內部狀態更新:

更新state屬性(getDerivedStateFromProps)=》判斷組件是否更新(shouldComponentUpdate)=》組件更新渲染(render)=》(getSnapshotBeforeUpdate)=》組件更新完成(componentDidUpdate)

組件卸載時執行:

組件銷毀(componentWillUnmount)

注意:

新版本使用了getDerivedStateFromProps代替了componentWillMount、componentWillReceiveProps、componentWillUpdate三個鉤子函數,如果在舊版本中使用將會警告提示。它必須要return一個null或者對象,并且會影響初始化的值以及修改的值。

getSnapshotBeforeUpdate鉤子必須與componentDidUpdate搭配使用否則會報錯。在舊版本中使用將會警告提示。必須要return一個null或者任何值,它將在最近一次渲染輸出(提交到DOM節點)之前調用。

二、生命周期新增函數詳解

static getDerivedStateFromProps(getDSFP)

首先這個新的方法是一個靜態方法,在這里不能調用this,也就是一個純函數。它傳了兩個參數,一個是新的nextProps ,一個是之前的prevState,所以只能通過prevState而不是prevProps來做對比,它保證了state和props之間的簡單關系以及不需要處理第一次渲染時prevProps為空的情況。也基于以上兩點,將原本componentWillReceiveProps里進行的更新工作分成兩步來處理,一步是setState狀態變化,更新 state在getDerivedStateFromProps里直接處理。

舊的React中componentWillReceiveProps方法是用來判斷前后兩個props是否相同,如果不同,則將新的props更新到相應的state上去。在這個過程中我們實際上是可以訪問到當前props的,這樣我們可能會對this.props做一些奇奇怪怪的操作,很可能會破壞state數據的單一數據源,導致組件狀態變得不可預測。

而在getDerivedStateFromProps中禁止了組件去訪問 this.props,強制讓開發者去比較nextProps與prevState中的值,以確保當開發者用到getDerivedStateFromProps這個生命周期函數時,就是在根據當前的props來更新組件的state,而不是去訪問this.props并做其他一些讓組件自身狀態變得更加不可預測的事情。

getSnapshotBeforeUpdate

在React開啟異步渲染模式后,在執行函數時讀到的DOM元素狀態并不一定和渲染時相同,這就導致在componentDidUpdate中使用的DOM元素狀態是不安全的(不一定是最新的),因為這時的值很有可能已經失效了。

與componentWillMount不同的是,getSnapshotBeforeUpdate會在最終確定的render執行之前執行,也就是能保證其獲取到的元素狀態與componentDidUpdate中獲取到的元素狀態相同。

這個方法并不常用,但它可能出現在UI處理中,如需要以特殊方式處理滾動位置的聊天線程等。并且會返回snapshot的值或null。例如:

class ScrollingList extends React.Component {

constructor(props) {

super(props);

this.listRef = React.createRef();

}

getSnapshotBeforeUpdate(prevProps, prevState) {

// 我們是否在 list 中添加新的 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>

);

}

}

上述例子中重點是從 getSnapshotBeforeUpdate讀取scrollHeight屬性,因為“render”階段生命周期(如 render)和“commit”階段生命周期(如 getSnapshotBeforeUpdate 和 componentDidUpdate)之間可能存在延遲。

生命周期修改的深層原因

因為React 16引入了Fiber機制,把同步的渲染流程進化為了異步的渲染流程,這么做的原因是同步渲染流程有個弊端:一旦開始就不能停下,大工作量的渲染任務執行時,主線程會被長時間的占用,瀏覽器無法即時響應與用戶的交互。

Fiber機制會把渲染任務拆解為多個小任務,并且每執行完一個小任務,就把主線程的執行權交出去,也就解決了上面的弊端。

然而,采用Fiber機制進行渲染時,render階段沒有副作用,可以被暫停,終止或重新啟動。就是這個重新啟動,會導致工作在render階段的componentWillMount、componentWillReceiveProps、componentWillUpdate存在重復執行的可能,所以它們幾個必須被替換掉。

三、Error boundaries

在React16之前,組件內的JS錯誤會導致React的內部狀態被破壞,并且在下一次渲染時產生無法追蹤的錯誤。這些錯誤基本上是由其他的非React組件代碼錯誤引起的。但React并沒有提供一種優雅的錯誤處理方式,也無法從錯誤中恢復。

然而部分UI的JS錯誤不應該導致整個應用的崩潰,為了解決這個問題,React引入了一個新的概念——錯誤邊界。

Error boundaries(錯誤邊界)是一個React組件,它可以捕獲并打印發生在其子組件數任何位置的JS錯誤,然后,渲染出備用UI,而非崩潰了的子組件。錯誤邊界可以在渲染期間、生命周期方法和整個組件樹的構造函數中捕獲錯誤。

但是錯誤邊界無法捕獲以下幾種錯誤:

  • 事件處理
  • 異步代碼
  • 服務端渲染
  • 自身錯誤

新版React給我們提供了兩個與錯誤處理相關的API:static getDerivedStateFromError和componentDidCatch。

只要在Class組件中定義static getDerivedStateFromError或componentDidCatch這兩個生命周期方法中的任意一個/兩個,那么這個組件就是一個錯誤邊界組件了。

static getDerivedStateFromError

getDerivedStateFromError是一個靜態方法。在渲染子組件的過程中,頁面更新之前,當發生了錯誤時,該方法就會運行。

它將拋出的錯誤作為參數并返回一個對象覆蓋掉當前組件的state。

class ErrorBoundary extends React.Component {

constructor(props) {

super(props);

this.state = { hasError: false };

}

static getDerivedStateFromError(error) { // 更新 state 使下一次渲染可以顯降級 UI return { hasError: true }; }

render() {

if (this.state.hasError) { // 你可以渲染任何自定義的降級 UI return <h1>Something went wrong.</h1>; }

return this.props.children;

}

}

componentDidCatch

componentDidCatch會在后代組件拋出錯誤時調用,因為它的執行時間比較晚,所以一般不支持改變組件state。

它接受兩個參數:

error:拋出的錯誤;

info: 帶有componentStack key的對象,其中包含有關組件引發錯誤的棧信息。

class ErrorBoundary extends React.Component {

constructor(props) {

super(props);

this.state = { hasError: false };

}

static getDerivedStateFromError(error) {

// 更新 state 使下一次渲染可以顯示降級 UI

return { hasError: true };

}

componentDidCatch(error, info) { // "組件堆棧" 例子: // in ComponentThatThrows (created by App) // in ErrorBoundary (created by App) // in div (created by App) // in App logComponentStackToMyService(info.componentStack); }

render() {

if (this.state.hasError) {

// 你可以渲染任何自定義的降級 UI

return <h1>Something went wrong.</h1>;

}

return this.props.children;

}

}

四、總結

React 16基于兩個原因做出了生命周期的調整:

 

  • 其一:為同步渲染改異步渲染的Fiber鋪路,把有可能多次執行的render階段中 componentWillMount/componentillUpdate/componentWillRecevieProps三個方法棄用;
  • 其二:為在一定程度上防止用戶對生命周期的錯用和濫用,把新增的getDerivedStateFromProps用static修飾,阻止用戶在其內部使用this。

分享到:
標簽:React
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定