介紹
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