iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 13
1
Software Development

Functional Programming in JS系列 第 13

[補充] HOF 的好友 HOC (Higher-Order Component)

了解 HOF (Higher-Order Function) 之後,就順便來補充他的好麻吉 Higher-Order Component (以下簡稱 HOC),因為他們概念真的很像。HOF 是 function 接受另一個 function 當成參數或 function 回傳 function,而 HOC 是作用在 Component 上。
HOC 的應用在 寫 React 時隨處可見,此篇也會以 React 為例。

什麼是 HOC?

A higher-order component is a function that takes a component and returns a new component.

以下就是最簡單的使用方式,可以看到 Componet 被包在另一個 Componet 裡

const App = higherOrderComponent(WrappedComponent);

實際上的 code 長這樣 ↓,其實也是蠻好理解的, higherOrderComponent 接受傳進來的 component WrappedComponent 當參數,然後回傳一個新的 React component 裡面包含 WrappedComponent

const higherOrderComponent = Component => props =>
  (
    <>
		  <h1>Hello World</h1>
			<Component {...props} /> 
            // props 會從母層傳下來 <App name='Hannah' />
	</>
)

const WrappedComponent = ({ name }) => (
	<p>I'm {name}</p>
)

const rootElement = document.getElementById('root');

const App = higherOrderComponent(WrappedComponent)
ReactDOM.render(<App name='Hannah' />, rootElement)

Hello World
I'm Hannah

higherOrderComponent 可以接受任何 Component,並可以不斷 Reuse(完整範例可以看 codepen)

Why use HOC

用上面例子看不大出來 HOC 的好處

The idea with HOC is to enhance components with functions or data.

High-Order Component 可以經由不同的組合 compose、覆寫 overwrite、編輯上層資料與UI ,成為一個新元件的函式,讓元件一直被重覆利用。

例如今天我想做三種時鐘,會依據地區不同而顯示不同時鐘在 dashboard 上,傳入的 data 時間是一樣的。
https://ithelp.ithome.com.tw/upload/images/20200913/20106426qtjaSG1Th2.jpg
三種 clock 除了會有不同長相跟不同 DOM,裡面也個別需要做一些不同的時間轉換

  • Hourglass 沙漏: 可能會把 24 小時轉換成沙漏的比例
  • Clock 一般時鐘: 24 小時會變成顯示 1 - 12
  • Digital 時鐘 可以顯示 1 - 24

這時候 HOC 就派上用場了,以下只是大概示範會長怎樣

const widgetDashboard = Component => props =>
  (
    <>
		  <h1>Dashboard</h1>
			<Component {...props} />
		</>
	)

const formatUnit = Component => ({ time, ...props }) => (
  <Component {...props} time={formatToUnit(time)}} />
);

const clock = ({ time, name }) => (
    // 一個時鐘的樣子
	<h1>{name} {time}</h1>
)

const digitalClock = ({ time, name }) => (
    // 數位時鐘的樣子
	<h2>{name} {time}</h2>
)

const hourglass = ({ time }) => (
    // 沙漏樣子
	<h3>{time}</h3>
)
// Clock
const App = widgetDashboard(*formatUnit(*clock))
ReactDOM.render(<App name='Clock' time='2020-09-10'/>, rootElement)

// Digital Clock
const App = widgetDashboard(digitalClock)
ReactDOM.render(<App name='digital Clock' time='2020-09-10'/>, rootElement)

// Hourglass
const App = widgetDashboard(*formatUnit(*hourglass))
ReactDOM.render(<App time='2020-09-10'/>, rootElement)

你可以隨意地組合 formatUnit 、跟不同種時鐘 component

Observations

  • HOC 並沒有 mutate component,可以發現回傳的 Component 並不是原本的而是新的,因為 HOC 是 Pure function。
  • HOC 最大的功用就是利用不同組合的元件,能夠不斷 reuse 並減少重覆的程式碼。

參考文章

如有錯誤或需要改進的地方,拜託跟我說。
我會以最快速度修改,感謝您

O.S. 每天都在自我懷疑為何要熬夜寫文章 orz,而且今天可是週末啊
不是應該好好休息結果完全沒休息到,超想棄賽的 XD

歡迎追蹤我的部落格,除了技術文也會分享一些在矽谷工作的甘苦。


上一篇
實作經典 HOF 之 filter、map、reduce
下一篇
Currying
系列文
Functional Programming in JS30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

2
一級屠豬士
iT邦大師 1 級 ‧ 2020-09-13 00:20:23

加油! 別放棄! 也別給自己太大壓力.

看更多先前的回應...收起先前的回應...
hannahpun iT邦新手 4 級 ‧ 2020-09-13 00:23:31 檢舉

屯太少文章的結果,是否要一結束就該囤明年的文章
/images/emoticon/emoticon20.gif

囤了,也有忘記發的,這在早期鐵人賽有網友有發生過這樣的人間慘劇.
FP 有很多精彩的可以講啦.順著自己的思路,享受一段思維激盪的旅程.
不要太在意別人的想法,或者想要仔細解釋,因為閱讀者的喜好或是觀點,
你無法掌握.這是外部因素.那就解耦合,不理啦,放飛自我吧.

hannahpun iT邦新手 4 級 ‧ 2020-09-13 00:45:10 檢舉

發現你是鐵人賽大師,參加過六屆太厲害了~~

不是六屆,有一次是參加了幾組,還有用別的帳號寫.因為有幫友要打劫紀念的衣服.那次這個站還在改版,一整個緊張刺激啊,最怕是寫了,但是忘記發.所以都還要準備清單檢查.

我要留言

立即登入留言