useEffect 介紹
useEffect
介紹
useEffect
是 React 中的一個 Hook,允許你在函數型組件中執行副作用操作。副作用操作通常是指那些會影響組件之外的事物,如數據請求、訂閱、DOM 操作或手動更改瀏覽器 API 等。
在類別組件中,這些副作用操作通常是在 componentDidMount
、componentDidUpdate
和 componentWillUnmount
等生命週期方法中處理。而在函數型組件中,useEffect
將這些功能整合到了同一個 API 中。
useEffect
的基本用法
語法:
1
2
3
4
5
6
useEffect(() => {
// 副作用邏輯
return () => {
// 清理邏輯(可選)
};
}, [dependencies]);
- 副作用邏輯:這段代碼在組件渲染後執行,可以是數據請求、DOM 操作等。
- 清理邏輯:可選,當組件卸載或依賴項發生變化時執行,用來清理之前的副作用。
[dependencies]
:依賴項數組,只有當數組中的值發生變化時,副作用邏輯才會重新執行。
範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `你點擊了 ${count} 次`;
}, [count]); // 只有 count 改變時,副作用才會執行
return (
<div>
<p>你點擊了 {count} 次</p>
<button onClick={() => setCount(count + 1)}>點擊我</button>
</div>
);
}
export default Counter;
在這個範例中:
- 每次
count
值發生變化時,useEffect
中的副作用代碼會執行,更新頁面的標題顯示當前的點擊次數。 - 依賴項
[count]
表示只有當count
發生變化時,副作用才會重新執行。
1. 依賴項數組
useEffect
的第二個參數是一個依賴項數組,用來告訴 React 只有當某些值改變時才重新執行副作用邏輯。根據依賴項的不同設置,useEffect
有以下三種情況:
(1) 沒有依賴項數組
如果不傳入第二個參數,副作用會在每次組件渲染後都執行(相當於每次 componentDidUpdate
都會執行),這可能會導致不必要的副作用執行。
1
2
3
useEffect(() => {
console.log('每次渲染後都執行');
});
(2) 空依賴項數組
如果依賴項數組為空,則副作用只會在組件第一次掛載(componentDidMount
)和最後卸載(componentWillUnmount
)時執行一次。
1
2
3
4
5
6
useEffect(() => {
console.log('只在組件掛載時執行');
return () => {
console.log('組件卸載時執行');
};
}, []);
(3) 具體依賴項
當提供具體的依賴項時,副作用只會在依賴項發生變化時執行。這是最佳的性能優化方式,避免了不必要的副作用執行。
1
2
3
useEffect(() => {
console.log('count 改變時執行');
}, [count]);
2. 清理副作用
在某些情況下,我們需要在組件卸載或依賴項改變之前清理之前的副作用。例如,在訂閱或設置計時器時,我們應該在組件卸載時取消訂閱或清除計時器,這樣可以避免內存洩漏。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';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);
return () => {
clearInterval(interval); // 在組件卸載時清除計時器
};
}, []);
return <p>計時器: {seconds} 秒</p>;
}
export default Timer;
在這個範例中:
- 每次
useEffect
被執行時,設置一個計時器,計時器每秒更新一次seconds
狀態。 - 當組件卸載或重新渲染時,
return
的清理函數會清除計時器,避免內存洩漏。
3. 多個 useEffect
你可以在一個組件中使用多個 useEffect
,每個 useEffect
都可以負責不同的副作用操作。React 會按照它們出現在代碼中的順序依次執行這些副作用。
範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
const [name, setName] = useState('');
// 更新頁面標題
useEffect(() => {
document.title = `你點擊了 ${count} 次`;
}, [count]);
// 每次 name 改變時執行
useEffect(() => {
console.log(`名字改變為: ${name}`);
}, [name]);
return (
<div>
<input value={name} onChange={(e) => setName(e.target.value)} />
<button onClick={() => setCount(count + 1)}>點擊我</button>
</div>
);
}
export default Example;
在這個範例中:
- 第一個
useEffect
用來更新頁面的標題,當count
改變時觸發。 - 第二個
useEffect
用來監聽name
的變化,當輸入框的內容變化時觸發。
4. useEffect
的常見應用場景
- 數據請求:
useEffect
常用於在組件掛載後進行數據請求(API 調用),然後將結果存儲到state
中。 - 訂閱/取消訂閱:在組件掛載時訂閱事件(如 WebSocket 連接),並在卸載時取消訂閱。
- 手動 DOM 操作:更新 DOM 元素(如設置頁面標題、滾動位置等)。
- 設置/清除計時器:設置間隔計時器並在卸載時清除計時器。
總結
useEffect
是 React 中處理副作用的強大工具,它讓函數型組件能夠實現類似類別組件的生命週期功能。通過正確使用依賴項數組和清理副作用,你可以有效地管理組件的狀態更新、數據請求和其他副作用操作。