Jeff的隨手筆記

學習當一個前端工程師

0%

『Day 8』Pure Function

前言

在學習 React 時,你可能會遇到一個名為 Pure Function(純函數)的概念。Pure Function 是一種簡單而實用的程式設計方式,其核心特點是:相同的輸入永遠會產生相同的輸出,並且不會影響函數外的任何資料。在 React 中,Pure Function 不僅讓程式碼更容易理解,還有助於構建穩定且可預測的應用程式。

什麼是 Pure Function?

Pure Function 是一個在程式設計中非常重要的概念,它有兩個主要特徵:

  1. 只管自己的事:函式不會改變在被呼叫之前就已存在的任何物件或變數
  2. 相同輸入,相同輸出:給定相同的輸入參數,永遠會得到相同的結果

讓我們看一個簡單的例子:

1
2
3
4
5
6
7
8
9
10
11
// 這是一個 Pure Function
function double(number) {
return 2 * number;
}

// 這不是一個 Pure Function
let count = 0;
function increment() {
count += 1; // 修改了外部變數
return count;
}

React 元件與 Pure Function 的關係

React 的設計理念高度符合 Pure Function 的特性。React 希望元件在相同的 props 和 state 下,總是渲染出相同的結果(JSX)。這種設計讓我們可以更容易地撰寫穩定的 UI 元件。

這就是為什麼當我們寫 React 元件時,應該避免直接修改外部的變數或狀態。讓我們看看一個常見的錯誤示例與改進後的寫法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let guest = 0;

// ❌ 錯誤示範:直接修改外部變數
function Cup() {
guest = guest + 1; // 不應該直接修改外部變數
return <h2>訪客 #{guest} 的茶杯</h2>;
}

// ✅ 正確示範:透過 props 來傳遞資料
function Cup({ guestNumber }) {
return <h2>訪客 #{guestNumber} 的茶杯</h2>;
}

function TeaParty() {
return (
<>
<Cup guestNumber={1} />
<Cup guestNumber={2} />
<Cup guestNumber={3} />
</>
);
}

為什麼 Pure Function 這麼重要?

在 React 中堅持使用 Pure Function 的設計理念,不僅僅是一種良好的程式設計習慣,更能帶來以下實質的好處:

  1. 可預測性:當元件表現得像 Pure Function,每次的渲染結果都是可預期的。這讓我們在開發時能更容易追蹤和理解元件的行為,減少意外的 bug。
  2. 易於測試:由於 Pure Function 的輸出只依賴於輸入,我們可以輕鬆地為元件撰寫單元測試。只需準備好測試資料,就能確保元件在不同情況下都能正確運作。
  3. 效能優化:React 能夠更有效地進行元件的快取和重新渲染的優化。因為 Pure Function 的特性,React 可以確定何時需要重新渲染元件,避免不必要的運算。
  4. 開發體驗:當遇到問題時,Pure Function 的特性讓除錯變得更直接。因為問題的來源更容易定位,我們能更快找出並解決問題。

什麼是Side Effects

在程式設計中,Side Effects(副作用)指的是函數執行時,除了返回結果之外,還影響到函數外部的行為或環境。例如:

  • 改變外部變數:例如,修改全域變數的值。
  • 執行外部操作:例如,向伺服器發送請求或寫入檔案。
  • 影響畫面:例如,直接更新網頁上的 DOM 元素。

這些都被稱為Side Effects,因為它們打破了函數的純粹性(Pure Function 的特性是沒有Side Effects)。

舉例來說:

1
2
3
4
5
6
7
8
9
10
11
12
13
let count = 0;

// Side Effects:改變外部變數
function increment() {
count += 1; // 修改了函數外的變數
return count;
}

// 無 Side Effects 的寫法
function incrementPure(currentCount) {
return currentCount + 1; // 只根據輸入返回結果,不影響外部
}

在 React 中,我們也會遇到Side Effects,尤其是在以下情況下:

  • 與伺服器互動:例如,從伺服器獲取資料(API 請求)。
  • 控制時間:例如,設定或清除計時器(setTimeoutsetInterval)。
  • 操作 DOM:例如,直接改變某個 HTML 元素的樣式或內容。

React 如何處理Side Effects?

React 鼓勵我們把副作用和純粹的 UI 渲染邏輯分開,這樣可以讓程式碼更易於維護。常見的處理方式包括:

1.事件處理器中執行:

當 Side Effects 是因為使用者操作(如按鈕點擊)而觸發時,將它放在事件處理器中是最直觀的方式。

1
2
3
4
5
6
7
function App() {
const handleClick = () => {
alert("按鈕被點擊了!"); // 這是副作用
};

return <button onClick={handleClick}>點擊我</button>;
}

2.使用 useEffect 處理:

當 Side Effects 是依賴於元件的渲染或更新時,React 提供了 useEffect Hook 來執行這些操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React, { useState, useEffect } from "react";

function App() {
const [count, setCount] = useState(0);

// 使用 useEffect 處理副作用:更新網頁標題
useEffect(() => {
document.title = `您點擊了 ${count} 次`; // 這是副作用
}, [count]); // 當 count 改變時執行副作用

return (
<button onClick={() => setCount(count + 1)}>
點擊次數:{count}
</button>
);
}

在這個例子中,useEffect 負責更新網頁標題,這是一個典型的 Side Effects 行為,因為它改變了函數外部的狀態(瀏覽器的標題欄)。

總結

Pure Function 是 React 的核心設計理念之一。它要求函數在相同輸入下產生相同輸出,且不影響外部狀態。React 元件應該像 Pure Function 一樣,確保一致的渲染結果,這不僅讓程式碼更可讀、易測試,也能帶來更高的效能。而對於副作用,則應在事件處理器或 useEffect 中妥善處理,從而實現更好的程式設計體驗和穩定性。