React 洗菜 —高階組件 (H.O.C.)

Lee Luciano
Jun 14, 2023

--

在JavaScript中,高階函數(Higher Order Functions)是指可以接受函數作為參數或callback function的函數,簡單來說就是將函數做為參數來傳遞運行,最簡單的例子就是我們常使用的 map, filter , forEach … 這類的array method,接受一個callback function的處理來產生新的陣列。

講講更實際一點的使用場景吧!假設你現在正在維護一個舊的專案,然後舊的專案裡一大堆翻不了的 💩 code,但你為了滿足需求,你可能需要用到原來 💩 code 裡面的特定 function 來處理新的功能,這種情況就可以使用(H.O.F)的形式來處理,這樣原本的 💩 code我不會影響到他,二來也能完成任務。

// 簡單舉例下面為一個數字*2的簡單邏輯💩code
function foo(num) {
return num * 2
}
// H.O.F.
function wrapFoo(num, cb) {
const double = cb(num);
// 假設result是我們最後要的
const result = { int: num, x2: double }
return result;
}

console.log(wrapFoo(7, foo)) // {int: 7, x2: 14}
// 這樣一來我沒有動到原本的💩code,同時透過💩code產生需要的結果。

相同的概念移植到component身上就促成現在的(Higher Order Component),在我們開發的過程中,我們常常希望在多個組件中使用相同的邏輯,這樣可以統整包括對組件應用特定的樣式、授權,或者添加狀態。

簡單來說你能理解成將原本輸出的對象改成組件本身,能接收另一個組件作為參數的組件,傳入的對象也能不僅限於函數本身,能擴大到 jsx 組件。

假設我們想要在開發中的多個組件添加特定的樣式,我們可以創建一個簡單的高階組件,將樣式對象添加到我們傳遞給它的組件中,而不是每次在組件中個別重寫。

function withStyles(Component) {
return props => {
const style = { padding: '0.2rem', margin: '1rem' }
return <Component style={style} {...props} />
}
}

const Button = (props) = <button {...porps}>Click me!</button>
const Text = (props) => <p {...props}>Hello World!</p>

const StyledButton = withStyles(Button)
const StyledText = withStyles(Text)

上述的概念取自於 styled Component, emotion.js 這類的UI Library,也就是運用上這樣的概念,導致他們沒辦法跳脫jsx為基底的框架,因為angular, vue就沒辦法這樣使用,但是(H.O.C.)所帶來的好處不僅僅只是侷限於樣式而已,想想看我們之前介紹React memo的那個章節,memo本身也是一種(H.O.C.)的應用,用來判斷傳遞進來的值需不需要重新渲染 — 文章連結

總之,這類的應用能夠大幅重整專案中繁瑣重複的邏輯,這也是 React 相較 Angular / Vue 之特別的地方,雖然其他框架也有對應的處理方法,主要也是靠借鏡相同的概念而提出的更新,(H.O.C.)用意是拿來整合相同部分的邏輯,也便於組件之間的模組化整合,這樣又能回過頭來思考如何利用Prototype Pattern 的概念來整合前端組件的部分了。

希望這次的分享可以讓大家多思考(H.O.C.)的實際使用情境,以及如何應用到目前開發的專案當中,期待下次的分享,我會努力更新的。

--

--