iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 9
0
Modern Web

Next.js + 各種套件組合系列 第 9

Next.js & Recompose

介紹
Recompose 可以使用 Functional Programing 的方式去組裝元件,這樣產生出來的元件對於渲染的 Cost 會比較小,而且他的所有包含Life Cycle,States,Handler,Props 都可以抽出來重複使用,Recompose 也支援 Rx.js 的資料方法開發 ,在比較複雜的需要多層 HOC 加工的時候更能顯示出 Recompose 強大的威力

安裝

babel-plugin-lodash 與 recompose

{
  "presets": ["next/babel"],
  "plugins": [
    ["lodash", { "id": ["lodash", "recompose"] }]
  ]
}

Next.js 在使用 Recompose 的時候 跟一般差不多,只是因為生命週期的關係要先使用setStatic去定義 getInitialProps,再去判斷是否需要 SSR,這邊也可以看到使用 Recompose 使用compose 去結合他提供的方法後產出一個 HOC 的物件在跟 stateless 的 function 結合 這樣stateless 就可以拿到 HOC 的 Props了

import { compose, withState, setStatic } from 'recompose'
const enhance = compose(
  setStatic(
    'getInitialProps',
    async ({ req }) => {
      const isServer = !!req
      // log if we're server or client side
      if (isServer) console.log('from server')
      else console.log('from client')
      // return a prop to know if we're server or client side
      return { isServer }
    }
  ),
  withState(
    'counter',
    'setCounter',
    0
  )
)

export default enhance(({ counter, setCounter, isServer }) => (
  <button onClick={() => setCounter(counter + 1)}>
    {isServer ? 'from server' : 'from client'} Counter:{counter}
  </button>
))

附記:因為 Recomopse 有滿多 API ,來說明幾個幫助理解

1.withState
有三個參數 第一個是StateName這個就單純是StateName,第二個是stateUpdaterName可以想像是setState,第三個就是初始化construct State 這樣就不難理解了


withState(
  stateName: string,
  stateUpdaterName: string,
  initialState: any | (props: Object) => any
): HigherOrderComponent

2.withStateHandlers

第一個參數是 construct State 第二個是 Handler 寫Method


withStateHandlers(
  initialState: Object | (props: Object) => any,
  stateUpdaters: {
    [key: string]: (state:Object, props:Object) => (...payload: any[]) => Object
  }
)

可以實際看個範例就更清楚了,使用 withStateHandlers 最後產出的也是 HOC 會把 state 當作props 傳入

  const Counter = withStateHandlers(
    ({ initialCounter = 0 }) => ({
      counter: initialCounter,
    }),
    {
      incrementOn: ({ counter }) => (value) => ({
        counter: counter + value,
      }),
      decrementOn: ({ counter }) => (value) => ({
        counter: counter - value,
      }),
      resetCounter: (_, { initialCounter = 0 }) => () => ({
        counter: initialCounter,
      }),
    }
  )(
    ({ counter, incrementOn, decrementOn, resetCounter }) =>
      <div>
        <Button onClick={() => incrementOn(2)}>Inc</Button>
        <Button onClick={() => decrementOn(3)}>Dec</Button>
        <Button onClick={resetCounter}>Reset</Button>
      </div>
  )

Recompose 上 還有許多常用組合的 API 底下有提供連結

總結

Next.js 上使用 Recompose 只需要加上 setStatic getInitialProps , 多一個 SSR 的生命週期,其他使用都一樣,強力好物推推

Next.js 提供的範例檔案
https://github.com/zeit/next.js/tree/canary/examples/with-recompose
Recompose 官方 Github
https://github.com/acdlite/recompose


上一篇
Next.js & Typescript
下一篇
Next.js & ApolloData(一) 基本設定
系列文
Next.js + 各種套件組合30

尚未有邦友留言

立即登入留言