昨天介紹了在 Function Component 中該如何操作 state 的方法(附上傳送門),今天這篇要來為大家介紹的就是第二個較常用到的 React Hooks : useEffect()
:實現在 Function Component 中操作生命週期的方法。
useEffect()
整合了原本 Class function 中的生命週期:
componentDidMount
、componentDidUpdate
和componentWillUnmount
等三個方法,並用來處理 Function Component 中的 side effect 。
所以白話文來說, useEffect()
這個 Hook 可以讓我們在 Function Component 中操作某些比較常使用到的生命週期方法。
不過關於最後一段說明中的 side effect 指的是什麼呢?
簡稱 Effect , 除了函式內所回傳的值或是執行之外,有可能會影響甚至是改變到其他狀態的情形。
官網中所提到的 side effect 範例就包含了:
備註:關於 Side Effect 更詳細的介紹可以操考這篇: Day 12: ES6篇: Side Effects(副作用)與Pure Functions(純粹函式),裡面有更完整的說明和補充唷!
那關於 useEffect()
這個 Hook 要怎麼樣在 Function Component 中來實現上述提及的三種生命週期的方法呢?
useEffect()
應用範例先從官網的範例當中一起來看在 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 中的監聽事件了,可以來期待一下唷!
那我們就下篇見ʘ‿ʘ