Jeff的隨手筆記

學習當一個前端工程師

0%

『Day 29』事件處理與 Effect差異

前言

最近在優化專案時,我深深體會到正確使用事件處理(Event Handler)和 Effect 的重要性。記得之前在處理一個即時聊天功能時,我把所有的邏輯都放在 Effect 裡面,結果不只效能變差,連除錯都變得特別困難。這個經驗讓我意識到,雖然這兩種機制都是用來處理副作用,但它們的使用時機和行為模式其實有著根本的差異。

今天就讓我分享一下這兩種機制的關鍵差異,以及在實務上如何選擇合適的工具。

認識兩種不同的副作用處理方式

在 React 中,處理副作用主要有兩種方式:事件處理和 Effect。它們看似相似,但實際上有著很大的差異:

事件處理(Event Handler)

1
2
3
4
5
6
7
8
9
function ChatRoom() {
function handleClick() {
// 由使用者觸發,只在點擊時執行
sendMessage(messageText);
}

return <button onClick={handleClick}>發送訊息</button>;
}

事件處理就像是餐廳的服務生,只有在客人呼喚時才會過來服務。它:

  • 只在特定互動(如點擊)時執行
  • 不會自動重新執行
  • 可以安全地讀取最新的狀態

Effect

1
2
3
4
5
6
7
8
9
10
11
function ChatRoom({ roomId }) {
useEffect(() => {
// 自動執行,負責與外部系統同步
const connection = createConnection(roomId);
connection.connect();
return () => connection.disconnect();
}, [roomId]);

return <div>聊天室:{roomId}</div>;
}

而 Effect 則像是餐廳的空調系統,會自動根據環境溫度調節。它:

  • 會自動執行
  • 當相依值改變時會重新執行
  • 主要用於同步外部系統

useEffectEvent

在實務上,有時我們需要在 Effect 中存取一些最新的值,但又不希望這些值觸發 Effect 重新執行。React 為此提供了 useEffectEvent

1
2
3
4
5
6
7
8
9
10
11
12
13
function ChatRoom({ roomId, theme }) {
const onConnected = useEffectEvent(() => {
// 可以讀取最新的 theme,但不會導致 Effect 重新執行
showNotification('已連線!', theme);
});

useEffect(() => {
const connection = createConnection(roomId);
connection.on('connected', onConnected);
return () => connection.disconnect();
}, [roomId]); // 不需要加入 onConnected
}

實務上的選擇指南

在開發時,我會問自己這些問題來決定使用哪種方式:

  1. 這個操作需要使用者觸發嗎?
    • 如果是,用事件處理
    • 如果需要自動執行,用 Effect
  2. 這個邏輯是否需要同步外部系統?
    • 如果是,用 Effect
    • 如果只是回應使用者操作,用事件處理

總結

理解事件處理和 Effect 的差異,不只能幫助我們寫出更好的程式碼,更能避免許多常見的效能問題。重要的是要記住:

  • 事件處理用於回應特定的使用者操作
  • Effect 用於自動同步外部系統
  • useEffectEvent 可以幫助我們在兩者之間取得平衡

這些概念可能一開始不太容易理解,但只要在實務中多加練習,相信很快就能掌握它們的精髓。