RN 組件的生命周期如下圖:

生命周期回呼函式
掛載
當組件實體被創建并插入 DOM 中時,其生命周期呼叫順序如下:
constructor()static getDerivedStateFromProps()render()componentDidMount()
注意:
下述生命周期方法即將過時,在新代碼中應該避免使用它們:
UNSAFE_componentWillMount()
更新
當組件的 props 或 state 發生變化時會觸發更新,組件更新的生命周期呼叫順序如下:
static getDerivedStateFromProps()shouldComponentUpdate()render()getSnapshotBeforeUpdate()componentDidUpdate()
注意:
下述方法即將過時,在新代碼中應該避免使用它們:
UNSAFE_componentWillUpdate()UNSAFE_componentWillReceiveProps()
卸載
當組件從 DOM 中移除時會呼叫如下方法:
componentWillUnmount()
錯誤處理
當渲染程序,生命周期,或子組件的建構式中拋出錯誤時,會呼叫如下方法:
static getDerivedStateFromError()componentDidCatch()
常用的生命周期方法
1、render()
render() 方法是 class 組件中唯一必須實作的方法,
當 render 被呼叫時,它會檢查 this.props 和 this.state 的變化并回傳以下型別之一:
- React 元素,通常通過 JSX 創建,例如,
<div />會被 React 渲染為 DOM 節點,<MyComponent />會被 React 渲染為自定義組件,無論是<div />還是<MyComponent />均為 React 元素, - 陣列或 fragments, 使得 render 方法可以回傳多個元素,,
- Portals,可以渲染子節點到不同的 DOM 子樹中,
- 字串或數值型別,它們在 DOM 中會被渲染為文本節點
- 布爾型別或
null,什么都不渲染,(主要用于支持回傳test && <Child />的模式,其中 test 為布爾型別,)
render() 函式應該為純函式,這意味著在不修改組件 state 的情況下,每次呼叫時都回傳相同的結果,并且它不會直接與瀏覽器互動,
如需與瀏覽器進行互動,請在 componentDidMount() 或其他生命周期方法中執行你的操作,保持 render() 為純函式,可以使組件更容易思考,
注意
如果
shouldComponentUpdate()回傳 false,則不會呼叫render(),
2、constructor()
如果不初始化 state 或不進行方法系結,則不需要為 React 組件實作建構式,
在 React 組件掛載之前,會呼叫它的建構式,在為 React.Component 子類實作建構式時,應在其他陳述句之前前呼叫 super(props),否則,this.props 在建構式中可能會出現未定義的 bug,
通常,在 React 中,建構式僅用于以下兩種情況:
- 通過給
this.state賦值物件來初始化內部 state, - 為事件處理函式系結實體
在 constructor() 函式中不要呼叫 setState() 方法,如果你的組件需要使用內部 state,請直接在建構式中為 this.state 賦值初始 state,
要避免在建構式中引入任何副作用或訂閱,如遇到此場景,請將對應的操作放置在 componentDidMount 中
3、componentDidMount()
componentDidMount() 會在組件掛載后(插入 DOM 樹中)立即呼叫,依賴于 DOM 節點的初始化應該放在這里,如需通過網路請求獲取資料,此處是實體化請求的好地方,
這個方法是比較適合添加訂閱的地方,如果添加了訂閱,請不要忘記在 componentWillUnmount() 里取消訂閱
你可以在 componentDidMount() 里直接呼叫 setState(),它將觸發額外渲染,但此渲染會發生在瀏覽器更新螢屏之前,如此保證了即使在 render() 兩次呼叫的情況下,用戶也不會看到中間狀態,請謹慎使用該模式,因為它會導致性能問題,通常,你應該在 constructor() 中初始化 state,如果你的渲染依賴于 DOM 節點的大小或位置,比如實作 modals 和 tooltips 等情況下,你可以使用此方式處理
4、componentDidUpdate()
componentDidUpdate() 會在更新后會被立即呼叫,首次渲染不會執行此方法,
當組件更新后,可以在此處對 DOM 進行操作,如果你對更新前后的 props 進行了比較,也可以選擇在此處進行網路請求,
componentDidUpdate(prevProps) { // 典型用法(不要忘記比較 props): if (this.props.userID !== prevProps.userID) { this.fetchData(this.props.userID); } }
你也可以在 componentDidUpdate() 中直接呼叫 setState(),但請注意它必須被包裹在一個條件陳述句里,正如上述的例子那樣進行處理,否則會導致死回圈,它還會導致額外的重新渲染,雖然用戶不可見,但會影響組件性能,不要將 props “鏡像”給 state,請考慮直接使用 props,
5、componentWillUnmount()
componentWillUnmount() 會在組件卸載及銷毀之前直接呼叫,在此方法中執行必要的清理操作,例如,清除 timer,取消網路請求或清除在 componentDidMount() 中創建的訂閱等,
componentWillUnmount() 中不應呼叫 setState(),因為該組件將永遠不會重新渲染,組件實體卸載后,將永遠不會再掛載它,
不常用的生命周期方法
并不太常用,它們偶爾會很方便,但是大部分情況下組件可能都不需要它們,
1、shouldComponentUpdate()
根據 shouldComponentUpdate() 的回傳值,判斷 React 組件的輸出是否受當前 state 或 props 更改的影響,默認行為是 state 每次發生變化組件都會重新渲染,
2、static getDerivedStateFromProps()
getDerivedStateFromProps 會在呼叫 render 方法之前呼叫,并且在初始掛載及后續更新時都會被呼叫,它應回傳一個物件來更新 state,如果回傳 null 則不更新任何內容,
此方法適用于 state 的值在任何時候都取決于 props,
派生狀態會導致代碼冗余,并使組件難以維護, 確保你已熟悉這些簡單的替代方案:
- 如果你需要執行副作用(例如,資料提取或影片)以回應 props 中的更改,請改用
componentDidUpdate, - 如果只想在 prop 更改時重新計算某些資料,請使用 memoization helper 代替,
- 如果你想在 prop 更改時“重置”某些 state,請考慮使組件完全受控或使用
key使組件完全不受控 代替,
3、getSnapshotBeforeUpdate()
getSnapshotBeforeUpdate() 在最近一次渲染輸出(提交到 DOM 節點)之前呼叫,它使得組件能在發生更改之前從 DOM 中捕獲一些資訊(例如,滾動位置),此生命周期的任何回傳值將作為引數傳遞給 componentDidUpdate(),
此用法并不常見,但它可能出現在 UI 處理中,如需要以特殊方式處理滾動位置的聊天執行緒等,
應回傳 snapshot 的值(或 null),
Error boundaries
Error boundaries 是 React 組件,它會在其子組件樹中的任何位置捕獲 JavaScript 錯誤,并記錄這些錯誤,展示降級 UI 而不是崩潰的組件樹,Error boundaries 組件會捕獲在渲染期間,在生命周期方法以及其整個樹的建構式中發生的錯誤,
如果 class 組件定義了生命周期方法 static getDerivedStateFromError() 或 componentDidCatch() 中的任何一個(或兩者),它就成為了 Error boundaries,通過生命周期更新 state 可讓組件捕獲樹中未處理的 JavaScript 錯誤并展示降級 UI,
僅使用 Error boundaries 組件來從意外例外中恢復的情況;不要將它們用于流程控制,
欲了解更多詳細資訊,請參閱 React 16 中的錯誤處理,
注意
Error boundaries 僅捕獲組件樹中以下組件中的錯誤,但它本身的錯誤無法捕獲,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/36903.html
標籤:JavaScript
