Higher Order Component(HoC) 學習

July 6, 2017

本篇文章記錄為開發 side project 感想。

這陣子花了一些時間學習了關於 react 的 Higher Order Component,這個概念其實出來已經有一段時間了,但是一直沒有好好的去認識,直到最近重寫了一個 side project 才開始使用 Higher Order Component 這個概念,我自己覺得整個寫起來的體驗真的是很好,尤其是在寫測試的時候感受更加明顯!

Functional Programming 在這幾年開始流行起來,最早大概就是 Redux 採用了 大量的 functional programming 概念來減少 side effect,對於 Redux 還不認識得朋友,可以在 egghead.io 上來學習 Redux,這是由作者 Dan Abramov 所錄製的教學影片 - Getting Started with Redux,講解了許多 Redux 的核心概念,很值得學習!

關於 functional programming 我自己也還在學習摸索的階段,但可以發現在 react 的生態圈大量採用了這個概念來開發相關的應用,撇除 react,functional programming 是很值得學習的!

什麼是 HOC

Higher Order Component 稱為「高階元(組)件」,又簡稱「HOC」,主要的概念就是重複使用 Component,我們最早開始寫 react 大概主要都是像 class Counter extends React.Component { ... },透過繼承 React.Component 接著撰寫相關的邏輯,你可能有許多邏輯或者是 lifecycle method 在你的 class 內,當需求一直增加的時候,你可能會發現你的 class 會越長越大,這時候我們就必須適當的切出一些區塊出來,而這些區塊或許也能提供其他的 Component 做 reuse。

Higher Order Component 它其實就一個 function 取得一個 Component 並回傳新的 Component,在這個 function 內,你可以對傳入的 Componet 做不同的 enhance,而得到一個全新的 Component。

在許多教學會看到許多範例使用 compose 來對 Component 做各種組合,透過組合的方式可以讓 Component 更加的彈性,compose 是來自 functional programming 的概念:

compose(f, g)(x) => f(g(x))

也就是我們以前所學過的數學式,我們帶入一些數字:

compose(square, addOne)(1) => square(addOne(1))

我們給入的數字是 1,我們先把這個數字加 1,接著把數字平方,我們得到 4

換個場景思考一下,香腸是們製作出來的呢哈哈?好像跟 compose 的概念很像吧!我們把豬肉灌進去,中間透過機器處理,得到了香腸!

同理,我們傳入一個 Component 進去,透過不同的 function 來處理,最後得到一個全新的 Component,這就是 Higher Order Component。

Presentational 和 Container Component

這裡我覺得有必要提到關於 PresentationalContainer 這兩種 Component 類型,未來你也會根據你的需要去區分這兩種 Component,這兩個 Component 的差別如以下:

資料來源:

Presentational ComponentContainer Component
用途怎麼看事情(markup, styles)怎麼做事情 (抓資料, 更新 state)
取得資料透過 props 得到資料訂閱整個應用程式的 State,例如 Redux 的 connect()
改變資料透過 props 接收到的 callbackDispatch action

為了撰寫可以 reuse 的 Component,大多都是使用 Presentational Component,我們只關心傳進來的資料我們要怎麼去做呈現,我們透過 Container Component 去得到我們需要的 state,再把這些 state 作為 props 傳下去給各個 Presentational Component。

Side Project

recompose counter

這次在開發 nextjs-redux-instagram 中用到了許多蠻新的東西,包括 next.jsredux-saga 還有今天本篇要分享的 recompose,其實很早之前 redux 很流行的時候,我也透過 Instagram API 做過類似的 side project,但是那時候我寫的東西真的是有夠糟的!所以在前陣子才打算利用一些新技術來嘗試重寫。

在這個 side project 主要用的技術大概分成這三大項:

  • Server Side Rendering
  • Async action
  • Higher Order Component

在 Server Side Rendering,我先透過 OAuth 認證,接著去跟 Instagram 取得 Access Token,必須拿到 Access Token 才可以去取得其他 API 資料。

選擇 redux-saga 主要是因為用到了 async action,但是用 redux-thunk 在做測試的時候需要做很多 mock,我覺得很麻煩,所以我就採用了 redux-saga,它可以很方便的寫測試,不需要額外的去做 mock,這讓我覺得很棒。

這次也嘗試了 recompose,感受一下 Higher Order Component 的威力,用起來真的感覺蠻棒的,我寫了幾個 Presentational Component,只關注如何去呈現資料,最後透過 compose 的方式將這些 Component 組合起來,不僅這樣,這樣讓我在測試上更加的容易。