iT邦幫忙

2021 iThome 鐵人賽

DAY 16
2
Modern Web

React.js 30 天學習全記錄系列 第 16

[ Day 16 ] React Hooks 中的 useEffect

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20210926/20134153h2N6P2AYml.png
昨天介紹了在 Function Component 中該如何操作 state 的方法(附上傳送門),今天這篇要來為大家介紹的就是第二個較常用到的 React Hooks : useEffect() :實現在 Function Component 中操作生命週期的方法。


useEffect()

整合了原本 Class function 中的生命週期: componentDidMountcomponentDidUpdatecomponentWillUnmount 等三個方法,並用來處理 Function Component 中的 side effect 。

所以白話文來說, useEffect() 這個 Hook 可以讓我們在 Function Component 中操作某些比較常使用到的生命週期方法。
不過關於最後一段說明中的 side effect 指的是什麼呢?

Side Effect

簡稱 Effect , 除了函式內所回傳的值或是執行之外,有可能會影響甚至是改變到其他狀態的情形。

官網中所提到的 side effect 範例就包含了:

  1. AJAX 非同步的資料取得
  2. 設定監聽事件
  3. 手動更改 Component 中的 DOM

備註:關於 Side Effect 更詳細的介紹可以操考這篇: Day 12: ES6篇: Side Effects(副作用)與Pure Functions(純粹函式),裡面有更完整的說明和補充唷!

那關於 useEffect() 這個 Hook 要怎麼樣在 Function Component 中來實現上述提及的三種生命週期的方法呢?


useEffect() 應用範例

改寫 Class Component 中的生命週期

先從官網的範例當中一起來看在 Class Component 中撰寫生命週期的方式:

// 建立一個 Class Component <Example>
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }
  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

延續前幾天的計數器範例,這邊是採用 Class Component 的生命週期 componentDidMount()componentDidUpdate() 兩種方法。當元件掛載於 DOM 上之後就會做第一次的網站標題渲染,之後只要監聽到點擊事件之後就會觸發 count 變數 +1 並重新渲染網站標題。其實我們是希望它在每次的渲染後再次執行一樣的內容,但是在 Class Component 中沒有這樣的方法,所以我們才會撰寫一樣的操作內容在兩個不同的生命週期當中。

備註:關於瀏覽器 document.title 這個 API 可以參考這個網站的介紹。

如果依照原本 Class Component 的寫法你就會發現我們會在不同的生命週期去做一樣的事情,那如果我們改用 React Hooks 的話會有怎樣的結果呢?

改用 useEffect() 撰寫

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

在 Function Component 中使用 useEffect() 方法,並在該方法內直接對元件操作 Render 後的行為。意思就是當該元件初次掛載並執行渲染時觸發一次 Hook 方法,或是在 state 中的資料有變化時也會再觸發一次該方法。

所以我們其實可以這樣來解讀 useEffect() 這個 Hook :

useEffect(() => {
    /* 操作 componentDidMount() 和 componentDidUpdate */
});

不過透過上述範例我們只有應用到了兩個生命週期而已,另外一個方法要怎麼應用呢?這時候我們就要來看 useEffect() 這個方法的第二個參數了。


useEffect() 的第二個參數

在上面範例我們只有應用到該 Hook 的第一個參數(也就是一個函式)。如果我們在該函式中 return 一個值且帶入一個函式時,我們就能使用到生命週期的 componentWillUnmount 的方法了,不過在這邊要記得加上 useEffect()第二個參數:陣列

在該陣列中加入變數後,當該變數的值產生改變時便會再次觸發 useEffect() 函示。

所以我們可以在有使用到第二個參數的 useEffect() 中這樣理解該函式:

useEffect(() => {
  /* 操作 componentDidMount() */
  return() => {
  /* 操作 componentWillUnmount() */
  }
}, []); 

在第二個參數的陣列中,如果沒有賦予任何變數的值(等同空陣列)的話,就代表不會有任何值的變動導致該 Hook 再次被觸發。因此就能夠在最後函式所 return 回來的內容中撰寫等同於 componentWillUnmount 的生命週期內容。

不過對於第二個參數的使用與否就會導致 useEffect() 這個 Hook 所操作的生命週期函式不同,因此在同一個 Function Component 中我們可以使用多個 useEffect() 來操作不同的變數


那今天對於 useEffect 的使用介紹就先告一個段落了!意外發現在這個章節花了比較多的時間去了解這個 Hook 的使用方式還有一些要注意的特性。
其實關於這個 Hooks Function 還有許多細節跟其他不同的用法,下面整理前輩大大們的文章給大家參考:

明天要開始為大家介紹 React 中的監聽事件了,可以來期待一下唷!
那我們就下篇見ʘ‿ʘ


上一篇
[ Day 15 ] React Hooks 中的 useState
下一篇
[ Day 17 ] React 中的事件處理
系列文
React.js 30 天學習全記錄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言