iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
0
自我挑戰組

玩轉 React 從0到1系列 第 16

【Day 16】React 元件的生命週期

  • 分享至 

  • xImage
  •  

前言

我們前面介紹了 JSX 是如何渲染到頁面上的,那現在我們要來介紹元件的生命週期,在 React 中生命週期大概可以拆分成三個階段,包含:
1.裝載過程(Mount): 元件第一次在 DOM 渲染的過程
2.更新過程(Update): 元件重新被渲染的過程
3.卸載過程(Unmount): 元件從 DOM 上被刪除的過程
我們接下來會一一介紹,那在各版本當中有發生變動,我們也會特別提出來。

裝載過程(Mount)

裝載過程依序調用的函數:

constructor -> static getDerivedStateFromProps -> componentWillMount -> render -> componentDidMount

  1. constructor 構造函數

是元件初始化的地方也是元件接收由父元件傳遞過來 props 的地方,它只會被呼叫一次,這個地方也可以針對需要回調的函數預先進行 bind 的動作

  1. getDerivedStateFromProps(props, state):

getDerivedStateFromProps 是 React 16.3 提供的新方法,就類似之前的 componentWillReceiveProps()

props 發生變化的時候會被調用,若是父元件重新渲染,它也會被調用會返回新的 props
使用場景: 當元件內部的 state 變化依賴於 props,調用該函數
注意:如果這個操作(效果)是依賴於props的更動,最好改寫在 componentDidUpdate

舉例而言:
src/multiCalculate.js

import React from 'react';
export default class MultiCalculate extends React.Component {
  constructor() {
    super();
    this.state = {
      currenctValue: 0,
    }
  }

  static getDerivedStateFromProps(props, state) {
    console.warn('取得 props 跟 state', props, state);
    return {
      currenctValue: props.data * 10
    }
  }

  render() {
    return (
      <div>
        <h1>當前 MultiCalculate 元件 currenctValue 值: {this.state.currenctValue}</h1>
      </div>
    )
  }
}

src/App.js

import React from 'react';
import MultiCalculate from './multiCalculate';

export default class App extends React.Component {
  constructor() {
    super();
    this.state = {
      data: 0,
    }
  }

  render() {
    return (
      <div>
        <h1>當前 App 元件 data 值 {this.state.data}</h1>
        <MultiCalculate data={this.state.data} />
        <button onClick={() => {this.setState({data: this.state.data + 1})}}>
          增加1
        </button>
      </div>
    )
  }
}

https://ithelp.ithome.com.tw/upload/images/20201005/2010996316P90QfznB.png

  1. componentWillMount(不推薦)

componentWillMount因為發生在元件渲染前,所以有許多人會在這裏初始化數據或是異步獲取數據,但如果是異步取得數據並不會等待數據返回後才進行渲染,React官方建議放在 constructor 去處理,所以 React16.3 後不推薦這方法。

  1. render

render() 是作為渲染用,可以返回以下幾種類型:

  • React 元素
  • Arrays
  • 片段(fragments)
  • 插槽(Portals)
  • 字串或數字(String && Numbers)
  • Boolean or Null
  1. componentDidMount

componentDidMount 是元件已經在實體的 DOM 呈現之後才會呼叫的方法,所以如果是想要在元件產生後先執行的動作都可以寫在 componentDidMount
使用場景: 通常會在這裏進行 數據請求(Ajax) 或是 加入事件監聽

更新過程(Update)

當 props 或是 state 發生變化時就會引起元件的更新進而引起 render 的重新渲染

更新過程依序調用的函數:

componentWillReceiveProps(nextProps,nextState) -> static getDerivedStateFromProps()
->shouldComponentUpdate -> componentWillUpdate -> render -> getSnapshotBeforeUpdate()
->componentDidUpdate

  1. componentWillReceiveProps(nextProps,nextState)(不推薦)

componentWillReceiveProps 是在 props 更新時觸發,一般用於 props 參數更新時同步 state 參數,但如果componentWillReceiveProps 直接調用父元件某些有調用setState的函數,會導致死循環,所以 React16.3 後不推薦這方法

  1. static getDerivedStateFromProps()

同 Mount 敘述

  1. shouldComponentUpdate

shouldComponentUpdate通過返回 truefalse來決定是否觸發新的渲染,如果是 false 則不觸發後續的 componentWillUpdate -> render() 和 componentDidUpdate()。

在這裡,可以進行像是 this.props 跟 nextProps 或是 this.state 跟 nextState 的比較,只有在返回true時後續動作才會執行,以下為程式碼:

shouldComponentUpdate(nextProps, nextState) {
  // this.props, this.state 代表原先的 props,state
  // nextProps, nextState 代表後續的 props.state
  if (nextProps.props.attribute !== this.props.attribute 
  || nextState.state.attribute !== this.state.attribute) {
    return true;
  }
  return false;
}
  1. componentWillUpdate(不推薦)

當接收到新的 props 或 state 時,在渲染前會執行該方法,一般是用於渲染前保存一些數據方便 render 後給值,但是因為 componentWillUpdatecomponentDidUpdate 有時間差 (componentWillUpdate經過渲染、計算、更新DOM元素,最後才調用componentDidUpdate),在這過程可能因為用戶行為而導致 DOM 發生新的變化,而 componentWillUpdate 獲取的資料可能就不可靠了,所以 React16.3 後不推薦這方法

  1. render

同 Mount 敘述

  1. getSnapShotBeforeUpdate(prevProps, prevState)

這個函數的作用是在 ComponentDidUpdate(真實DOM 更新前),進行快照然後將參數傳給ComponentDidUpdate,裡面的兩個參數 prevPropsprevState 分別表示更新前的 props和更新前的state,這裏的返回值是一個snapshot,這個函數都會伴隨著componentDidUpdate一起使用。

  1. componentDidUpdate(prevProps, prevState, snapshot)

這個方法是在更新完成後調用,而第三個參數 snapshot 來自於 getSnapShotBeforeUpdate(prevProps, prevState)的返回值。
可以使用 setState,會觸發 re-render,所以要注意判斷避免死循環

卸載過程(Unmount)

卸載過程調用的函數:

componentWillUnmount()

  1. componentWillUnmount

是在元件卸載或銷毀前調用,這個方法主要用來做清理的工作,像是:

  • 取消定時器
  • 取消事件綁定
  • 取消請求

生命週期

https://ithelp.ithome.com.tw/upload/images/20201005/20109963TkJt0qhp4z.png

https://ithelp.ithome.com.tw/upload/images/20201005/20109963gO9YpnOuhi.png

結論

  • 介紹了 React 的 生命週期
    /images/emoticon/emoticon07.gif

上一篇
【Day 15】React 關於事件處理
下一篇
【Day 17】React 中發送 Ajax 請求以及 Mock數據
系列文
玩轉 React 從0到130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言