iT邦幫忙

2021 iThome 鐵人賽

DAY 22
0
Modern Web

用30天更加認識 React.js 這個好朋友系列 第 22

Day22-React Life Cycle 篇-上篇(介紹生命週期圖 & Mounting)

這篇要介紹的是 React 元件的生命週期(Life Cycle)。

要認識生命週期的話我們可以先從這個 Life Cycle 圖表網站 瞭解,以下兩張圖是從圖表網站截的圖,上面那張代表整個 Life Cycle 最重要的部分,下面那張則是多呈現一些比較次要的函式。

不過這些圖片出現的函式,大多數都是在 class component 使用,如 componentDidMount、componentDidUpdate、componentWillUnmount...還有非函式的 constructor。functional component 需要透過 react hook 才能擁有類似生命週期的操作。

即使如此,還是可以透過圖片去理解 React 的 Life Cycle,並不會影響太大。

如果你在別人介紹的 Life Cycle 文章看到 componentWillMount、componentWillUpdate 等沒有出現在圖片上的函式,是因為它們已經被廢棄

元件生命週期三大階段

如圖所示,主要有分成三個階段:

  • Mounting(componentDidMount) 建立元件,當元件被加入到 DOM 中時會觸發
  • Updating(componentDidUpdate) 更新元件,當元件的 props 或 state 更新,重新渲染 (re-rendered) DOM 時會觸發
  • Unmounting(componentWillUnmount) 註銷元件,當元件從 DOM 中被移除時會觸發

除了這三個階段外,還有 Error handling,做錯誤處理

Mounting

在 Mounting 的部分,可以看到有五個階段,以下將一一介紹:

第一階段: constructor()

這個東西在 class component 使用,主要是在初始化元件的 state 和綁定一些事件,在建立 constructor() 前必須先呼叫 super(props) 這行程式去傳入 props。

範例:

constructor(props) {
  super(props);
  // Don't call this.setState() here!
  this.state = { counter: 0 };
  this.handleClick = this.handleClick.bind(this);
}

第二階段: getDerivedStateFromProps()

這個函式是靜態方法(static method),無法操作 class 內的方法&變數。

靜態方法牽涉到物件導向的觀念,就不詳細說明了。

static getDerivedStateFromProps(props, state)它接受了兩個參數,更新的 props 和當前 state,我們可以使用這個函式讓 props 去修改 state,最後回傳的是一個要更新的 state 物件或是 null,表示不更新 state。

範例:

import React from 'react';
import ReactDOM from 'react-dom';
  
class App extends React.Component {
  render() {
    return <Child name="Tom"></Child>;
  }
}
  
class Child extends React.Component{
  constructor(props){
    super(props);
    this.state = { name: "Jean" };
  }

  static getDerivedStateFromProps(props, state) {
    if(props.name !== state.name){
      return { name: props.name };
    }
    return null;
  }

    render(){
       return (
        <div> My name is {this.state.name }</div>
       )
    }
}
                      
export default App;

如程式碼所示,如果 props 的 name 和 state 的 name 不同,就更新 state 的 name 值,若相同就不更新。

另外,在 React 官網介紹 getDerivedStateFromProps()也時有說到有幾種時機不適合使用這個函式:

  1. 執行 side effect
  2. 重新計算資料
  3. 重置 state

最後一點是這個函式不太常用到,如果想深入了解以上三個時機推薦閱讀三個你不需要getDerivedStateFromProps的時機 這篇文章,解說的相當詳細。

第三階段: render()

這個函式一定要在 class component 內撰寫,會回傳以下幾種類型:

  1. JSX 建立的 React element
class Example extends React.Component {
  render() {
    return <h1>Hello world!</h1>;
  }
}
  1. React fragment
class Example extends React.Component {
  render() {
    return <>Hello world!</>;
  }
}
  1. 陣列
class Example extends React.Component {
  render() {
    return [
      <div key="1">Hello</div>,
      <div key="2" >World</div>
    ];
  }
}
  1. 字串
class Example extends React.Component {
  render() {
    return "Hello world!";
  }
}
  1. Portal
class Example extends React.Component {
  render() {
    return createPortal(this.props.children, document.querySelector("body"));
  }
}
  1. Boolean
  2. null

要注意的是 render() 這個函式必須是純粹函式,所以不能做一些變更 state 或呼叫 api 等有 side effect 的事情。

第四階段: 更新 DOM 元素和 Refs

第五階段: componentDidMount()

當元件呈現在網頁上時就會呼叫這個函式,對應到 React hook 就是 useEffect 會進行呼叫。它用來處理那些有 DOM 元素之後才能做的事,以及更新 state、call api 取得資料。

下篇將會繼續介紹未介紹到的階段。


上一篇
Day21-React 簡易動畫篇-下篇
下一篇
Day23-React Life Cycle 篇-下篇(Updating & Unmounting & Error handling & Render Phase & Commit Phase)
系列文
用30天更加認識 React.js 這個好朋友32

尚未有邦友留言

立即登入留言