Recompose でいい感じに Higher-order Components(HoCs)を作る


Recompose

RecomposeはHigher-order Componentsをサポートするライブラリ。

Higher-order Componentsについては下記記事で軽くまとめた。

どんなライブラリ?

  • HoCsを作成・提供するための便利関数ライブラリ
  • 「lodash的なノリで、関数群をまとめている」とのこと
  • 作者はflummoxreact-actionなど、reactやredux関連を多く作っているライブラリの作者。
  • まだ 0.20で微妙にAPIは安定してない部分もアリ

まずはサンプル

例: 未サポートブラウザの時にメッセージ出す

説明だけだとわかりづらいので、個人的に一番とっつきやすかったbranchを使って、特定のブラウザの場合に「お使いのブラウザはサポートされてません」と出すサンプルを書いてみる。

普通のReact.Componentで書く(Recomposeナシ)

export const NotSupportedMessage = () => <h3>お使いのブラウザはサポートされておりません</h3>

export default class MainApp extends Component{
  isSupportedPlatform(){
    if(/*ブラウザが未サポートかの判定*/){
      return false
    }
    return true
  }
  render() {
    if(!this.isSupportedPlatform()){
      return <NotSupportedMessage />
    }
    return (
      <div className="SomeApp">
        何らかのアプリケーション
      </div>
    )
  }
}

まあこれでも全然問題ない。が、本筋のSomeAppの部分までスッとたどり着いていないし、このあたりの処理が肥大化すると色々辛いことになりそうなのが見える。

Higher-order Componentで書く(Recomposeアリ)

import branch from 'recompose/branch'
import renderComponent from 'recompose/renderComponent'

// branchは、下記のように引数を取る
// branch(判定関数, trueの時, falseの時)

const NotSupportedMessage = () => <h3>お使いのブラウザはサポートされておりません</h3>

const SomeMyApp = () => (
  <div className="SomeApp">
    何らかのアプリケーション
  </div>
)

const isSupportedBrowser = () => {
  if(/*ブラウザが未サポートかの判定*/){
    return false
  }
  return true
}

const withBrowserCheck = branch(
  isSupportedBrowser,
  component => component, // trueの時は、受け取っていた引数をそのまま流用
  renderComponent(NotSupportedMessage)
)

const MainApp = withBrowserCheck(SomeMyApp)

withBrowserCheckがHigerOrderCoponentとして、ReactComponentを渡すと、ブラウザチェックを挟んだ状態のSomeMyAppReactComponentとして返してくれるようになる。

また、もし「desktopだけの判定もいれたい」とかになったら、下記のような感じで拡張されるので、本筋のSomeMyAppの肥大化が防げる

const MainApp = compose(withBrowserCheck, withDeviceCheck)(SomeMyApp)

Recomposeが提供してる関数の種類など

だいたいこんなあたりがある。

まとめ

雑感・良かった所

  • Stateless Functionを推してる感じがする。
  • HoCsの下記の利点が活かしやすい
  • いわゆるテンプレート的なviewとロジックをどんどん分離出来る感覚がとても良い
    • withPropsあたりをうまく扱えると、Componentが素のtemplateっぽくなっていって良い
  • jsxの記述が減らしやすい
    • テンプレート的な扱いをするComponent以外だとほとんどjsxいらないとすら言えそう
  • HoCsは簡単に自前実装出来るが、ちょっとだけ自前より嬉しい事が多い。
    • いい感じにHoCsの名前をつけてくれたりするので、デバッグに役立つ
    • composeなど、自前だと微妙に面倒な部分を提供してくれる

良くなかった所、注意点

  • HoCsに慣れるまでちょっとつらい。
  • やりすぎると可読性酷くなりかねない
  • jsxの記述量減っても、全体のコード量増えそう
    • 一周回って「あれ、これjsxの方が簡素に書けてね?」みたいな事がたまにある