Higher-order Components
ReduxなどReact関連のライブラリで時々出てくるHigher-order Componentsについて色々わかんなくなったので調べたことをメモ程度に留めてまとめる
通称 HoCとかHoCsとか略されるが、この記事では Higher-order Components、HoCsで統一しておく。
Higher-order Components(HoCs)とは?
語の元となったのは高階関数(Higher-order function)であると思われる。
高階関数は、「関数を引数にとり、関数を戻り値とする」ような関数の事。
HoCsも同様で、「Componentを引数にとり、Componentを戻り値とする」ような関数(または実装パターン)の事 1
なぜこんな概念が出てきたのか?
この記事が良く出される
Mixins Are Dead. Long Live Composition
ざっくり要約すると
- ES2015のclass記法においては、mixinは使えなくなった
- 今後、classのmixinが取り込まれる可能性はある
- けど、mixinはそもそも色々モロい部分もある
- 多分Reactに復帰することも積極的ではなさそう
- そこで、Higher-order Componentsですよ。という話
Mixinって何?またはなんだっけ?
ちょっと忘れているのでおさらい。
ReactのcreateClass
で利用できる、いわゆるMixin。
継承をせずに、Componentに同一の挙動を与えるものだった。
ざっくりどんな実装をしているのか?
https://gist.github.com/sebmarkbage/ef0bf1f338a7182b6775
HoCsの初出(らしい)こちらのGistがわかりやすい。
噛み砕いてコードリーディングしてみる
- 登場するのはこの2つ
- Enhancer = コンポーネントを受け取ってコンポーネントを返す関数。HoCs
- MyComponent = 例として適応される側のコード
- Enhancerを見てみる
-
Enhancer = (ComposedComponent) => class extends Component...
という部分がかなり特殊に見える。- 「ワンライナーでやってるけどこういうことだよ」と展開後のコメントで書かれている
- やっていることは「
ComposedComponent
」という元のComponentを受けて、匿名のクラス(class extends Component
)を返している - この時に、
componentDidMount
だったり、state
の利用だったりをして、mixinがやっていたようなことをやっている
-
-
export default Enhance(MyComponent)
で、HoCs適応済みのComponentを返している。
ということで、やっていること自体はとても簡素。好みによってはprops.children
でも代用出来るかもしれない(多分コードの簡素さと、DOMが深くならないとかの理由でclassでwrapしてる方を採用しているんだと思う)。
各ライブラリにおける実例
HoCsは、Reduxやらreact-routerやら有名ライブラリで使われている。以下見つけられた例。
-
react-redux#connent
- 例:
connect(null, actionCreators)(TodoApp)
というHoCsを提供している
- 例:
-
react-router#withRouter
-
withRouter
という関数が、HoCs。
-
-
react-i18next#translate
- i18nをするライブラリ。
translate
をHoCsとして提供している
- i18nをするライブラリ。
-
baobab-react#higher-order-components
- 名前まま。
- Qiitaにもこれを利用した実例の記事があったbaobab-reactを使って軽量fluxを回す
HoCs に関する記事、参考文献など
-
Higher-Order Componetを使ってES6 Class記法でmixinっぽいことをする
- 探した限り唯一ぐらいの日本語記事
- Higher Order Components: Theory and Practice
- React Fundamentals: Higher Order Components (replaces Mixins)(動画)
- What are Higher Order Components?
- Structuring React Applications: Higher-Order Components
-
React Higher Order Components in depth
-
「関数を適応したComponent」を指している場合もある。若干このあたり理解甘い。 ↩