Released 2023-03-22

Modified 2023-03-22

Tech

1396Words (7min read)

[Day 29] React 元件的生命週期方法 - 嘗試 30 日寫文充版挑戰

Title Image

Photo by React on React

前言 - Prologue

嘗試寫 30 天文充實版面 (跳過假日 ლ(́◕◞౪◟◕‵ლ) ) 更新文章的 Day 29

React 是一個用於構建用戶界面的 JavaScript 庫,每個元件都有生命週期,生命週期是指元件在其存在期間經歷的各個階段。

正文 - Main text

生命週期方法可在不同的階段執行相應的操作,例如:初始化狀態、更新 DOM、綁定事件等等。

生命週期三階段

React 元件的生命週期可以分為三個階段:

1. Mounting(掛載)階段

這個階段是指當一個元件被創建並插入到 DOM 中時發生的階段。

此階段將調用以下方法:

  • constructor():這個方法是元件的建構函數,它會在元件被創建時被調用。
  • getDerivedStateFromProps():這個方法會在元件創建時和接收新的 props 時被調用。
  • render():這個方法會根據當前的 stateprops 返回元件的 JSX 模板。
  • componentDidMount():這個方法會在元件被插入到 DOM 中之後立即調用。

2. Updating(更新)階段

這個階段是指當一個元件的 propsstate 發生改變時發生的階段。

此階段將調用以下方法:

  • getDerivedStateFromProps():這個方法會在元件接收新的 props 時被調用。
  • shouldComponentUpdate():這個方法會在元件更新之前被調用,用於判斷是否需要重新渲染元件。
  • render():這個方法會根據當前的 stateprops 返回元件的 JSX 模板。
  • getSnapshotBeforeUpdate():這個方法會在 render() 方法之後、元件被更新之前被調用,用於獲取更新前的 DOM 狀態。
  • componentDidUpdate():這個方法會在元件被更新之後立即調用。

3. Unmounting(卸載)階段

這個階段是指當一個元件從 DOM 中移除時發生的階段。

此階段將調用以下方法:

  • componentWillUnmount():這個方法會在元件被卸載之前被調用,用於清除元件所佔用的資源。

React lifecycle methods diagram

Photo by React lifecycle methods diagram on wojtekmaj

生命週期方法

當一個 React 元件被創建時,會經過以下生命週期方法:

1. constructor()

元件的建構函數,它會在元件被創建時被調用,可以初始化元件的狀態或綁定事件。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({ count: this.state.count + 1 });
  }

  // ...
}

上方例子在 constructor() 初始化了 count 狀態,並且綁定了 handleClick 方法的 this


2. getDerivedStateFromProps()

元件創建時和接收新的 props 時被調用,可以根據 props 更新元件的狀態。

class MyComponent extends React.Component {
  static getDerivedStateFromProps(props, state) {
    if (props.count !== state.count) {
      return { count: props.count };
    }
    return null;
  }

  // ...
}

上方例子使用 getDerivedStateFromProps() 來更新 count 狀態,如果 props.countstate.count 不相等,就返回一個新的狀態對象。


3. render() 根據當前的 stateprops 返回元件的 JSX 模板,可以定義元件的外觀和行為。

class MyComponent extends React.Component {
  render() {
    return (
      <div>
        <h1> Count: { this.state.count } </h1>
        <button onClick={ this.handleClick }> Increment </button>
      </div>
    );
  }

  // ...
}

上方例子使用 render() 返回了一個包含計數器和按鈕的 JSX 模板。


4. componentDidMount()

在元件被插入到 DOM 中後立即調用,可以執行一些副作用操作,例如:發送網路請求或註冊事件監聽器。

class MyComponent extends React.Component {
  componentDidMount() {
    console.log("Component is mounted");
  }

  // ...
}

上方例子在 componentDidMount()console.log 打印了一則消息,以確認元件已經被插入到 DOM 中。


5. shouldComponentUpdate()

在元件更新之前被調用,用於判斷是否需要重新渲染元件。

可以定義一些條件,只有滿足這些條件時才重新渲染元件,這動作可以提高元件的效率,從而避免不必要的渲染操作。

class MyComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.value === this.props.value && nextState.count === this.state.count) {
      return false;
    }
    return true;
  }

  // ...
}

上方例子使用 shouldComponentUpdate() 來判斷當前的 propsstate 是否需要更新。如果 nextProps.valuethis.props.value 相等,並且 nextState.countthis.state.count 相等,就返回 false,表示不需要更新元件。


6. getSnapshotBeforeUpdate()

在元件更新之前被調用,用於捕獲更新前的 DOM 狀態,可以返回一個值,這個值會作為 componentDidUpdate() 的第三個參數。

class MyComponent extends React.Component {
  getSnapshotBeforeUpdate(prevProps, prevState) {
    const list = document.getElementById("list");
    return list.scrollHeight;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    if (snapshot !== null) {
      const list = document.getElementById("list");
      list.scrollTop += list.scrollHeight - snapshot;
    }
  }

  // ...
}

上方例子使用 getSnapshotBeforeUpdate() 捕獲了列表更新前的滾動高度,並且在 componentDidUpdate() 中使用這個值來保持滾動位置不變。


7. componentDidUpdate()

在元件更新之後被調用,可以執行一些副作用操作,例如:發送網路請求或註冊事件監聽器。

class MyComponent extends React.Component {
  componentDidUpdate(prevProps, prevState) {
    if (prevProps.value !== this.props.value) {
      console.log("Value has been updated");
    }
  }

  // ...
}

上方例子使用 componentDidUpdate() 檢查當前的 props 是否已經更新,如果是就打印一則消息。


8. componentWillUnmount()

在元件被卸載之前被調用,可以清除一些副作用操作,例如:取消網路請求或移除事件監聽器。

class MyComponent extends React.Component {
  componentWillUnmount() {
    console.log("Component is unmounting");
  }

  // ...
}

上方例子使用 componentWillUnmount() 打印一則消息,以確認元件已經被卸載。

參考資料 - Reference

[1] [react] 生命週期(life cycle) | PJCHENder 未整理筆記

https://pjchender.dev/react/react-life-cycle/

[2] React lifecycle methods diagram

https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

[3] State 和生命週期 – React

https://zh-hant.reactjs.org/docs/state-and-lifecycle.html

[Day 29] React 元件的生命週期方法 - 嘗試 30 日寫文充版挑戰

https:///en/blog/49

Author

Kama

Read more from Tech
lightbox-image
Toggle Button - Red Pandas Icons by svgrepo.com

Copyrights © 2023 Kama, All Rights Reserved.