ReactJS - 元件生命週期



在 React 中,元件的生命週期表示元件在其存在期間的不同階段。React 提供回撥函式,以便在 React 生命週期每個階段都附加功能。在本章中,讓我們學習 React 元件的生命週期(以及相關的 API)。

生命週期 API

每個 React 元件都有三個不同的階段。

  • 掛載 − 掛載表示在給定的 DOM 節點中渲染 React 元件。

  • 更新 − 更新表示在狀態更改/更新期間在給定的 DOM 節點中重新渲染 React 元件。

  • 解除安裝 − 解除安裝表示刪除 React 元件。

React 提供了一系列生命週期事件(或回撥 API),用於附加功能,這些功能將在元件的不同階段執行。生命週期的視覺化以及生命週期事件(API)呼叫的順序如下所示。

Life Cycle

constructor() − 在 React 元件的初始構造階段呼叫。用於設定元件的初始狀態和屬性。

render() − 在元件構造完成後呼叫。它在虛擬 DOM 例項中渲染元件。這在 DOM 樹中指定為元件的掛載。

componentDidMount() − 在元件在 DOM 樹中初始掛載後呼叫。這是呼叫 API 端點和執行網路請求的好地方。在我們的時鐘元件中,可以在這裡設定 setInterval 函式以每秒更新狀態(當前日期和時間)。

componentDidMount() { 
   this.timeFn = setInterval( () => this.setTime(), 1000); 
}

componentDidUpdate()類似於 ComponentDidMount(),但在更新階段呼叫。在此階段可以執行網路請求,但僅當元件的當前屬性和先前屬性之間存在差異時。

API 的簽名如下所示:

componentDidUpdate(prevProps, prevState, snapshot)
  • prevProps − 元件的先前屬性。

  • prevState − 元件的先前狀態。

  • snapshot − 當前渲染的內容。

componentWillUnmount() − 在元件從 DOM 中解除安裝後呼叫。這是清理物件的好地方。在我們的時鐘示例中,我們可以在此階段停止更新日期和時間。

componentDidMount() { 
   this.timeFn = setInterval( () => this.setTime(), 1000); 
}

shouldComponentUpdate() − 在更新階段呼叫。用於指定元件是否應該更新。如果它返回 false,則更新將不會發生。

簽名如下所示:

shouldComponentUpdate(nextProps, nextState)
  • nextProps − 元件即將到來的屬性

  • nextState − 元件即將到來的狀態

getDerivedStateFromProps − 在初始和更新階段以及 render() 方法之前呼叫。它返回新的狀態物件。在屬性更改導致狀態更改的情況下,它很少使用。它主要用於動畫上下文中,其中需要元件的各種狀態才能執行平滑動畫。

API 的簽名如下所示:

static getDerivedStateFromProps(props, state)
  • props − 元件的當前屬性

  • state − 元件的當前狀態

這是一個靜態方法,無法訪問 this 物件。

getSnapshotBeforeUpdate − 在渲染的內容提交到 DOM 樹之前呼叫。它主要用於獲取有關新內容的一些資訊。此方法返回的資料將傳遞給 ComponentDidUpdate() 方法。例如,它用於維護新生成內容中的使用者滾動位置。它返回使用者滾動位置。此滾動位置由 componentDidUpdate() 用於設定實際 DOM 中輸出的滾動位置。

API 的簽名如下所示:

getSnapshotBeforeUpdate(prevProps, prevState)
  • prevProps − 元件的先前屬性。

  • prevState − 元件的先前狀態。

生命週期 API 的工作示例

讓我們在我們的 react-clock-app 應用程式中使用生命週期 API。

步驟 1 − 在您喜歡的編輯器中開啟 react-clock-hook-app

開啟 src/components/Clock.js 檔案並開始編輯。

步驟 2 − 從建構函式中刪除 setInterval() 方法。

constructor(props) { 
   super(props); 
   this.state = { 
      date: new Date() 
   } 
}

步驟 3 − 新增 componentDidMount() 方法並呼叫 setInterval() 以每秒更新日期和時間。此外,儲存引用以稍後停止更新日期和時間。

componentDidMount() { 
   this.setTimeRef = setInterval(() => this.setTime(), 1000); 
}

新增 componentWillUnmount() 方法並呼叫 clearInterval() 以停止日期和時間更新呼叫。

componentWillUnmount() { 
   clearInterval(this.setTimeRef) 
}

現在,我們已經更新了 Clock 元件,並且元件的完整原始碼如下所示:

import React from 'react';

class Clock extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         date: new Date()
      }      
   }
   componentDidMount() {
      this.setTimeRef = setInterval(() => this.setTime(), 1000); 
   }
   componentWillUnmount() {
      clearInterval(this.setTimeRef)
   }
   setTime() {
      this.setState((state, props) => {
         console.log(state.date);
         return {
            date: new Date()
         }
      })
   }
   render() {
      return (
         <div>
            <p>The current time is {this.state.date.toString()}</p>
         </div>
      );
   }
}
export default Clock;

接下來,開啟 index.js 並使用 setTimeout 在 5 秒後從 DOM 中刪除時鐘。

import React from 'react';
import ReactDOM from 'react-dom';
import Clock from './components/Clock';

ReactDOM.render(
   <React.StrictMode>
      <Clock />
   </React.StrictMode>,
   document.getElementById('root')
);
setTimeout(() => {
   ReactDOM.render(
      <React.StrictMode>
         <div><p>Clock is removed from the DOM.</p></div>
      </React.StrictMode>,
      document.getElementById('root')
   );
}, 5000);

使用 npm 命令提供應用程式。

npm start

開啟瀏覽器並在位址列中輸入 https://:3000 並按 Enter 鍵。

時鐘將顯示 5 秒,然後將從 DOM 中刪除。透過檢查控制檯日誌,我們可以發現清理程式碼已正確執行。

Interface DOM

在 Expense Manager 應用中的生命週期 API

讓我們在 Expense Manager 中新增生命週期 API,並在每次呼叫 API 時記錄它。這將深入瞭解元件的生命週期。

步驟 1 − 在您喜歡的編輯器中開啟 expense-manager 應用程式。

接下來,使用以下方法更新 ExpenseEntryItemList 元件。

componentDidMount() {
   console.log("ExpenseEntryItemList :: Initialize :: componentDidMount :: Component mounted");
}
shouldComponentUpdate(nextProps, nextState) {
   console.log("ExpenseEntryItemList :: Update :: shouldComponentUpdate invoked :: Before update");
   return true;
}
static getDerivedStateFromProps(props, state) {
   console.log("ExpenseEntryItemList :: Initialize / Update :: getDerivedStateFromProps :: Before update");
   return null;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
   console.log("ExpenseEntryItemList :: Update :: getSnapshotBeforeUpdate :: Before update");
   return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
   console.log("ExpenseEntryItemList :: Update :: componentDidUpdate :: Component updated");
}
componentWillUnmount() {
   console.log("ExpenseEntryItemList :: Remove :: componentWillUnmount :: Component unmounted");
}

步驟 2 − 使用 npm 命令提供應用程式。

npm start

開啟瀏覽器並在位址列中輸入 https://:3000 並按 Enter 鍵。

接下來,檢查控制檯日誌。它將在初始化階段顯示生命週期 API,如下所示。

ExpenseEntryItemList :: Initialize / Update :: getDerivedStateFromProps :: Before update 
ExpenseEntryItemList :: Initialize :: componentDidMount :: Component mounted

刪除一個專案,然後檢查控制檯日誌。它將在更新階段顯示生命週期 API,如下所示。

ExpenseEntryItemList :: Initialize / Update :: getDerivedStateFromProps :: Before update 
ExpenseEntryItemList.js:109 ExpenseEntryItemList :: Update :: shouldComponentUpdate invoked :: Before update 
ExpenseEntryItemList.js:121 ExpenseEntryItemList :: Update :: getSnapshotBeforeUpdate :: Before update 
ExpenseEntryItemList.js:127 ExpenseEntryItemList :: Update :: componentDidUpdate :: Component updated

最後,刪除所有生命週期 API,因為它可能會影響應用程式效能。僅當情況需要時才應使用生命週期 API。

廣告