首頁  >  文章  >  web前端  >  React 生命週期方法

React 生命週期方法

王林
王林原創
2024-09-05 06:38:41911瀏覽

在 React 中,生命週期方法是在元件存在的不同階段呼叫的特殊方法。它們可讓您控制元件在安裝、更新或卸載等各個階段發生的情況。隨著 React 16.8 中 React Hooks 的引入,函數式元件也可以管理自己的副作用,但生命週期方法在類別元件中仍然很重要。以下是最常用的生命週期方法的詳細介紹:

安裝

React 中的掛載階段是指元件被建立並插入 DOM 的過程。此階段涉及按特定順序呼叫的一系列生命週期方法,允許開發人員在渲染元件之前對其進行初始化和配置。以下是安裝階段中每個方法的詳細分解(按執行順序排列):

1. 建構函數(props)

目的:

  • 建構子是建立元件實例時呼叫的第一個方法。它用於初始化組件的狀態並綁定事件處理程序。

  • 在建構函式中,可以透過直接給this.state賦值一個物件來設定初始狀態。您通常也會使用 super(props) 將 props 傳遞給基底 Component 類,以確保元件正確初始化。

範例:

React Lifecycle Methods

備註:

  • 建構函式在元件的生命週期中只會呼叫一次。

  • 您應該避免建構函式中的副作用(例如網路請求或訂閱)並為 componentDidMount 保留這些任務。

2. 靜態 getDerivedStateFromProps(props, 狀態)

目的:

  • 這是一個靜態方法,在渲染之前調用,無論是在初始安裝期間還是在更新期間。它允許元件根據 props 的變化更新其狀態。

  • 它傳回一個物件來更新狀態,如果不需要狀態更新則傳回 null。

範例:

React Lifecycle Methods

備註:

  • 很少需要這個方法,因為 React 的資料流通常是透過直接傳遞 props 來處理的。

  • 它用於需要從 props 導出狀態的特殊情況。

3. 渲染()

目的:

  • render 方法是類別元件中唯一必需的生命週期方法。它透過傳回 React 元素來確定元件的 UI 應該是什麼樣子。

  • 這個方法是純粹的,這意味著它不應該修改元件狀態或與 DOM 互動。

範例:

React Lifecycle Methods

備註:

  • render 方法可以傳回各種值,包括 JSX 元素、陣列、片段、入口網站、字串、數字或 null。

  • 由於渲染是純粹的,請避免此方法中的副作用或狀態突變。

4. 組件DidMount()

目的:

  • 此方法在元件安裝(即插入 DOM 中)後立即呼叫。它是運行副作用的完美場所,例如從 API 獲取資料、設定訂閱或初始化第三方庫。

  • componentDidMount 是安裝階段呼叫的最後一個方法,使其成為任何 DOM 操作的理想選擇。

範例:

React Lifecycle Methods

備註:

  • 由於 componentDidMount 在初始渲染後被調用,更新其中的狀態將觸發重新渲染。這在獲取資料或與 DOM 互動時很常見。

  • 如果你在這裡設定了訂閱或事件監聽器,請記得在 componentWillUnmount 中清理它們,以避免記憶體洩漏。

更新中

React 中的更新階段是指元件因狀態或 props 的變化而重新渲染的過程。在此階段中,會以特定順序呼叫多個生命週期方法,使您能夠控制元件對這些變更的反應方式。以下按照執行順序詳細介紹了更新階段涉及的每個方法:

1.靜態 getDerivedStateFromProps(props, 狀態)

目的:

  • 當收到新的 props 或 state 時,會在渲染元件之前呼叫此靜態方法。它允許元件根據 props 的變化更新其內部狀態。

  • 它傳回一個更新狀態的對象,如果不需要更新則傳回 null。

範例:

React Lifecycle Methods

備註:

  • 此方法在需要與 props 同步 state 的場景中很有用。

  • 每次更新都會呼叫它,因此請避免此處進行繁重的計算。

2.shouldComponentUpdate(nextProps, nextState)

目的:

  • 當收到新的 props 或 state 時,在渲染之前呼叫此方法。它允許您控制組件是否應該更新。傳回true(預設)表示元件將更新;傳回 false 表示不會。

  • 主要用於透過防止不必要的重新渲染來優化效能。

範例:

React Lifecycle Methods

備註:

  • 在初始渲染期間或使用forceUpdate() 時不會呼叫此方法。

  • 此處避免複雜的邏輯,因為如果處理不當,可能會導致效能問題或錯誤。

3. 渲染()

目的:

  • 呼叫 render 方法,根據元件的目前狀態和 props 產生下一個版本的虛擬 DOM。

  • 它是純粹的,這意味著它不應該修改組件狀態或與 DOM 互動。

範例:

React Lifecycle Methods

備註:

  • 由於渲染是純粹的,任何狀態或道具的變更都應該反映在傳回的 JSX 中。

  • 避免渲染中的副作用(例如直接修改 DOM 或發出網路請求)。

4. getSnapshotBeforeUpdate(prevProps, prevState)

目的:

  • 此方法在虛擬 DOM 的變更實際反映到真實 DOM 之前呼叫。它允許您在可能更改之前捕獲一些資訊(例如當前滾動位置)。

  • 從此方法傳回的值會作為第三個參數傳遞給 componentDidUpdate。

範例:

React Lifecycle Methods

備註:

  • 此方法對於在 DOM 變更之前捕獲有關 DOM 的資訊特別有用,例如在更新期間保持滾動位置。

  • 經常與componentDidUpdate一起使用。

5. componentDidUpdate(prevProps, prevState, snapshot)

目的:

  • 更新發生後立即呼叫此方法。這是執行任何 DOM 操作、網路請求或基於更新的其他副作用的好地方。

  • 它接收先前的 props 和 state,以及 getSnapshotBeforeUpdate 傳回的值(如果有)。

範例:

React Lifecycle Methods

備註:

  • 此方法對於執行 DOM 更新後需要發生的操作很有用。

  • 避免在 componentDidUpdate 中設定狀態,除非將其包裝在條件中以防止無限循環更新。

解除安裝

React 中的卸載階段發生在從 DOM 中刪除元件時。此階段有一個生命週期方法,可讓您在元件被銷毀之前執行任何必要的清理任務。正確處理此階段對於防止記憶體洩漏、懸空事件偵聽器或元件刪除後可能持續存在的其他副作用至關重要。

1. 組件WillUnmount()

目的:
componentWillUnmount 在元件被卸載和銷毀之前立即呼叫。此方法用於清理活動,例如:

  • 取消網路請求。

  • 清除計時器或間隔。

  • 刪除事件偵聽器。

  • 清理訂閱(例如,來自 Redux、WebSockets 等)。

  • 使 componentDidMount 或其他生命週期方法中所建立的任何副作用失效或清除。

範例:

React Lifecycle Methods

在此範例中:

  • 組件安裝(componentDidMount)時啟動計時器。

  • 在 componentWillUnmount 中清除計時器,以確保元件從 DOM 移除後不會繼續運作。這對於防止潛在的記憶體洩漏或意外行為至關重要。

主要考慮因素:

  • 防止記憶體洩漏:如果在 componentDidMount 中設定了事件監聽器或間隔,則必須在 componentWillUnmount 中將其刪除以防止記憶體洩漏。如果不這樣做,可能會導致您的應用程式隨著時間的推移消耗更多記憶體或出現意外行為。

  • 清理訂閱:如果您的元件訂閱了外部資料來源(如 Redux 儲存、Firebase、WebSocket 連線等),您應該在 componentWillUnmount 中取消訂閱。這可確保您的元件在被刪除後不再對這些來源的更新做出反應。

  • 沒有 setState: 由於元件即將被銷毀,因此您不應該在 componentWillUnmount 中呼叫 setState。這樣做不會有任何效果,因為元件不會重新渲染。

  • 非同步清理:如果您的清理涉及非同步操作(例如取消網路要求),請確保正確處理這些操作以避免競爭條件或嘗試與不再使用的組件進行交互存在。

常見用例:

  • 計時器和間隔: 清除 setTimeout 或 setInterval 實例,以避免它們在組件卸載後運行。

  • 事件監聽器: 刪除附加到視窗、文件或任何 DOM 元素的事件監聽器,以防止它們在元件卸載後觸發。

  • 訂閱: 取消訂閱資料流或外部服務(例如 WebSockets、Firebase、Redux 儲存)。

  • 網路要求:如果在要求完成之前卸載元件,則取消正在進行的網路要求。這可以使用 Axios 等提供取消令牌的庫來完成。

最佳實務:

  • 如果在 componentDidMount 或任何其他生命週期方法中設定了副作用,請務必清除 componentWillUnmount 中的副作用。

  • 注意非同步操作,以確保它們不會無意中與已卸載的元件互動。

  • 避免任何假設元件在呼叫 componentWillUnmount 後將繼續存在的邏輯。

錯誤處理

React 中的錯誤處理階段旨在捕獲和處理渲染期間、生命週期方法以及組件下整個樹的構造函數中發生的錯誤。這是透過使用類別組件中稱為錯誤邊界的特殊生命週期方法來完成的。

誤差邊界概述

  • 錯誤邊界是 React 元件,它可以在其子元件樹中的任何位置捕獲 JavaScript 錯誤,記錄這些錯誤,並顯示後備 UI,而不是使整個應用程式崩潰。這可以防止錯誤傳播到應用程式的根目錄,從而使應用程式更具彈性。

1. 靜態 getDerivedStateFromError(錯誤)

目的:

  • 當渲染階段、生命週期方法或任何子元件的建構函式中拋出錯誤時,將呼叫此靜態方法。

  • 它允許您更新狀態,以便下一個渲染將顯示後備 UI。

用法:

  • 此方法接收作為參數拋出的錯誤,並傳回一個更新組件狀態的物件。

  • 透過在此方法中設定狀態,您可以呈現一個後備 UI,通知使用者出現了問題。

範例:

React Lifecycle Methods

備註:

  • 此方法可讓您控制發生錯誤時渲染的內容。例如,您可以選擇呈現通用錯誤訊息或自訂錯誤元件。

  • 它通常用於設定可以觸發後備 UI 渲染的錯誤狀態。

2. componentDidCatch(錯誤,訊息)

目的:

  • 在後代元件拋出錯誤後呼叫此方法。它用於記錄錯誤訊息或執行副作用,例如向錯誤追蹤服務報告錯誤。

  • 與 getDerivedStateFromError 不同,此方法可用於捕獲有關錯誤以及發生錯誤的組件堆疊追蹤的其他詳細資訊。

用法:
此方法接收兩個參數:

  • 錯誤:拋出的錯誤。

  • info:具有 componentStack 屬性的對象,其中包含一個字串,其中包含有關哪個元件引發錯誤的資訊。

範例:

React Lifecycle Methods

備註:

  • componentDidCatch 對於記錄錯誤或將錯誤傳送到監控服務(例如 Sentry、LogRocket)特別有用。

  • getDerivedStateFromError 有助於渲染後備 UI,而 componentDidCatch 則專注於捕獲和記錄錯誤詳細資訊。

如何使用誤差邊界

  • 包裝組件: 錯誤邊界可用於包裝任何組件或組件集。這可以全域完成(例如,圍繞整個應用程式)或更選擇性地完成(例如,圍繞更容易出錯的元件)。

範例:

React Lifecycle Methods

在此範例中,ErrorBoundary 包裝了 MyComponent。如果 MyComponent 或其任何子元件拋出錯誤,ErrorBoundary 將捕獲該錯誤並顯示後備 UI。

主要考慮因素:

錯誤邊界捕捉以下場景中的錯誤:

  • 渲染期間。

  • 生命週期方法中(包括類別組件中的方法)。

  • 在子組件的建構子中。

錯誤邊界不會捕捉以下場景中的錯誤:

  • 事件處理程序(可以使用事件處理程序本身內的 try/catch 區塊來擷取錯誤)。

  • 非同步程式碼(例如 setTimeout、requestAnimationFrame)。

  • 伺服器端渲染。

  • 錯誤邊界本身拋出的錯誤(儘管您可以嵌套錯誤邊界來捕獲此類錯誤)。

最佳實踐:

  • 使用錯誤邊界來防止整個應用程式因小的、孤立的錯誤而崩潰。

  • 在應用中可能容易出錯的部分周圍放置錯誤邊界,例如第三方組件或處理複雜邏輯的組件。

  • 確保錯誤邊界提供使用者友善的後備 UI,通知使用者出現了問題。

理解這些生命週期方法將幫助你更好地管理 React 元件中的狀態、props 和副作用。

功能組件中的生命週期方法

在函數式元件中,React 的 useEffect hook 是處理副作用和生命週期方法的主要方式。 useEffect 鉤子可以複製類似類別元件生命週期方法(如 componentDidMount、componentDidUpdate 和 componentWillUnmount)的行為。以下詳細介紹了 useEffect 的工作原理以及它與這些生命週期方法的關係。

基本文法

React Lifecycle Methods

  • 第一個參數(效果): 放置副作用邏輯的函數。此函數可以傳回一個清理函數,用於在元件卸載時或效果重新運行之前清理資源。

  • 第二個參數(依賴項): 一組依賴項,用於決定何時應重新運行效果。如果此數組中的任何值發生變化,則會再次觸發效果。

useEffect 作為 componentDidMount

要複製 componentDidMount 的行為(在組件安裝後運行一次),您可以使用帶有空依賴數組 [] 的 useEffect。

範例:

React Lifecycle Methods

  • 行為:此效果僅在初始渲染後運行一次,類似於類別元件中的 componentDidMount。

useEffect 作為 componentDidUpdate

為了模仿 componentDidUpdate,您可以使用帶有依賴項的 useEffect。只要任何依賴項發生變化,效果就會運作。

範例:

React Lifecycle Methods

  • 行為:效果在每次渲染後運行,其中依賴項(count 或 someProp)發生變化,就像 componentDidUpdate 一樣。

useEffect 飾演 componentWillUnmount

要複製 componentWillUnmount,您需要從 useEffect 傳回一個清理函數。此清理函數將在元件卸載時或效果重新運行之前執行。

範例:

React Lifecycle Methods

  • 行為:清理函數在元件即將卸載時運行,類似於 componentWillUnmount。

在一個 useEffect 中處理所有三種生命週期方法

在許多情況下,單一 useEffect 可以處理元件的安裝、更新和卸載階段。這是一個示範這一點的範例:

範例:

React Lifecycle Methods

  • 安裝:效果在初始渲染時運行一次。

  • 更新:每當 someProp 更改時效果就會運作。

  • 卸載:當元件卸載時或由於依賴項變更而重新運行效果之前,清理函數將運行。

控制useEffect的執行頻率

useEffect 的行為由依賴陣列控制:

  • 無依賴數組:效果在每次渲染後運行。

  • 空依賴陣列 []: 此效果僅在初始渲染後執行一次(模仿 componentDidMount)。

  • 特定依賴項:只要任何指定的依賴項發生更改,效果就會運作。

  • 範例: 沒有依賴陣列

React Lifecycle Methods

  • 行為:效果在每次渲染(初始和更新)後運行。

常見陷阱和最佳實踐

  • 避免丟失依賴項: 始終將 useEffect 中使用的所有狀態和 props 包含在依賴項數組中,以避免陳舊的閉包和錯誤。

  • 多個 useEffect 呼叫: 在單一元件中使用多個 useEffect 鉤子是很常見的,建議使用多個 useEffect 鉤子,每個鉤子負責特定的副作用。這使程式碼更加模組化並且更易於管理。

  • 清理: 始終考慮清理涉及訂閱、計時器或組件卸載或重新觸發效果時應釋放的任何其他資源的效果。

有效地理解和使用 useEffect 可讓您在功能元件中以乾淨、可預測的方式管理副作用,提供與類別元件具有生命週期方法相同的功能。

以上是React 生命週期方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn