可以取代 Class Component 的神兵利器之一,無疑是 useState 還有本篇介紹的 useEffect。

useEffect 基本運作的機制

在 Class Component 中,有著生命週期的 API,生命週期代表著一個元件從誕生到結束,在 Vue 也有相似的概念,每個階段有不同的 API 可以操作。

為了測試 useEffect 如何在元件中運作,下方寫了一個範例:

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

export default function App() {
  console.log('first');
  const [msg, setMsg] = useState('default');
  useEffect(() => {
    console.log('useEffect');
  });

  return (
    <>
      {console.log('render')}
      <button onClick={() => setMsg('default')}>1</button>
      <button onClick={() => setMsg('change1')}>2</button>
      <button onClick={() => setMsg('change2')}>3</button>
      <h1>{msg}</h1>
    </>
  )
}

當每次 render 的時候,看到 console.log 的順序是,而且每點選不同按鈕顯示不同內容也是一樣:

'first';
'render';
'useEffect'

也就是不管頁面是第一次編譯或是重新編譯,useEffect 都會執行。

如果想要每當狀態改變時就執行 useEffect 的話,就加上第二個參數,並在陣列內給值,例如:

useEffect(() => {
  console.log('useEffect');
}, [msg]);

如果參數沒有給值的話,則會變成只在首次編譯畫面時才會執行 useEffect

這是因為參數內的值沒有改變,所以 useEffect 就不會執行;那麼如果在同一個頁面,由於值是一樣的,所以也是不會執行。

其他觸發方式

useEffect 還有其他運用的地方,例如想要在 state 的值改變前做其他事情的話,就可以在 useEffect 的函式中回傳一個函式:

useEffect(() => {
  // do some thing
  return () => {
    // do another thing
  }
}, [])

下方做了一個範例:

執行的順序是: ```jsx useEffect(() => { (A) return () => { (B) } },[]) ``` * 當元件編譯完,會執行 (A) * 當元件內的 state 改變而重新渲染的話,會先執行 (B) 再執行 (A) * 當元件被移除時,會執行 (B) ## 適合使用 useEffect 的情境 由於 `useEffect` 會在編譯完執行的特性,所以也就非常適合拿來使用串接 API 取得資料時使用。 下方是使用 `useEffect` 來串接 API 的範例,使用的是 [政府資料開放平台](https://data.gov.tw/) 中的臺北市空品每小時監測資料,比對出士林區及臭氧的相關資訊: See the Pen <a href='https://codepen.io/bucky0112/pen/QWpJPNL'>useEffect-demo</a> by Bucky Chu (<a href='https://codepen.io/bucky0112'>@bucky0112</a>) on <a href='https://codepen.io'>CodePen</a>.