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

useEffect 基本運作的機制

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 的順序是,而且每點選不同按鈕顯示不同內容也是一樣:

1
2
3
'first';
'render';
'useEffect'

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

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

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

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

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

其他觸發方式

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

1
2
3
4
5
6
useEffect(() => {
// do some thing
return () => {
// do another thing
}
}, [])

下方做了一個範例:

執行的順序是:

1
2
3
4
5
6
useEffect(() => {
(A)
return () => {
(B)
}
},[])
  • 當元件編譯完,會執行 (A)
  • 當元件內的 state 改變而重新渲染的話,會先執行 (B) 再執行 (A)
  • 當元件被移除時,會執行 (B)

適合使用 useEffect 的情境

由於 useEffect 會在編譯完執行的特性,所以也就非常適合拿來使用串接 API 取得資料時使用。

下方是使用 useEffect 來串接 API 的範例,使用的是 政府資料開放平台 中的臺北市空品每小時監測資料,比對出士林區及臭氧的相關資訊: