Functional ComponentsとrecomposeでらくらくReactプログラミング

こんにちは。Nulab Appsチームの_fpです。Nulabではそれぞれのプロジェクトに合ったWeb Frameworkを使った開発を行なっており、Nulab AppsではReactを使用しています。

さて、Reactで苦労するポイントといえばいろいろありますが、中でもやはり状態管理とライフサイクルイベントハンドラRefとDOMのあたりではないでしょうか。

実装方法はいくつかありますが、ー般的なのは公式ドキュメントにあるようにReact.Componentを継承したクラスに機能を実装することかと思います。

ただ、いくつかクラスを作ると、だんだん似たような状態やライフサイクルを持つものばかりになることも少なくありません。

そこで、今回はFunctional ComponentsとHOCの組み合わせについて紹介してみたいと思います。サンプルコードは末尾のCodePenで試すことができます。

Functional ComponentsとHOC

まず、Functional Componentsとは、stateもlifecycleも持たず、propsを受け取りElementを返すだけのコンポーネントです。
Functionalの意味は、文字通りただのJavaScript関数だからだそうです。
ES6/JSXではこのように記述します。

次に、Higher-Order Component(HOC)とはコンポーネントを引数に取りコンポーネントを戻り値とするような関数です。
日本語に訳すとすれば高階コンポーネントになるでしょうか。関数を引数にしたり、関数を戻り値とするような関数を高階関数と呼ぶのと似ています。
有名なものでは、Reduxのconnectや、recomposeがあります。

今回は、Functional Componentsとrecomposeの組み合わせを紹介したいと思います。

recomposeに含まれるHOCの紹介

withState()

ステートの値とそのステートを更新するアップデータをpropsとして渡します。

これと、stateとsetStateをpropsに含むFunctional Componentを組み合わせて、ステートフルなコンポーネントを作ることができます。

withStateHandlers()

ステートの値と複数のハンドラをpropsとして渡します。複数のハンドラを持つことができるので、状態遷移をカプセル化したい場合に適しています。

withRenderProps()

recompose 0.27.1で追加された、HOCを適用したコンポーネントに渡されるpropsをRender Propsの引数にするというものです。Render PropsとはElementを返す関数をpropsに渡す手法のことで、特にprops.childrenに関数を渡すことをFunction as Child Componentsと呼んだりします。
先ほどのwithStateと組み合わせると、

のように、コンポーネントとしてJSXの中に記述すると、その子要素へのパラメータとしてwithStateのステートとアップデータが渡されていることがわかります。

lifecycle()

componentDidMountやcomponentWillUnmountといったlifecycleイベントを扱います。
初回表示時にデータをロードしたい場合や、addEventListenerを使いたい場合にも利用できます。

lifecycle自体は子に何も渡さないので、次のcomposeで他のHOCと組み合わせて使われることが多いと思います。

compose()

複数のHOCを組み合わせたHOCを返します。よくある使い方として、

のように、異なる機能を持つ複数のHOCを組み合わせるというものがあります。
最初のwithStateによってpropsにinputRefが追加されているので、lifecycleの中ではthis.propsを通じて参照できます。

使用例

カウンタ

withStateHandlerの例として紹介したenhanceWithCounterStateを使うと、次のようにカウンタを作ることができます。
ハンドラはbindする必要はなく、直接指定することもArrow Functionでパラメータを渡すこともできます。

inputの初回表示時にフォーカスを当てる

focus()を呼ぶにはRefを取得する必要がありますが、composeの例にあるenhanceWithAutofocusとwithRenderPropsを使うと、Functional Componentで実現できます。

CodePen

以上の例は、こちらのCodePenで試すことができます。

是非Forkしていろいろ試してみてください!

まとめ

以上、よく使うものを中心に解説してみましたが、Functional ComponentsとHOCを組み合わせることで必要な機能だけをピンポイントに実現できることが分かります。
アプリケーションが複雑化するにつれて状態管理が大変になったりコードが冗長になったりしがちで、それはReactにおいても例外ではありませんが、再利用性の高いコンポーネントでシンプルに記述することで可読性の高いコードが実現できます。

それでは、楽しいReactライフを!

開発メンバー募集中

より良いチームワークを生み出す

チームの創造力を高めるコラボレーションツール

製品をみる