TL;DR
- React で横断的関心事を扱う HOC、Render Props、Hooks について、5 本の参考記事から長所と短所、使う場面をまとめたスクラップ
- 作者の結論は、基本は Hooks を使い、HOC と Render Props は限られた条件のときだけ使う、である
内容
HOC
HOC は React のコンポジションの性質から生まれる設計パターンで、横断的関心事を扱う。すべてのデータが props 経由で渡るので、コンポーネントがシンプルになりやすく、テストもしやすい。一方で、props の名前が衝突する、コンポーネントのネストが深くなる、静的型付けが複雑になる、呼び出し元からどの props が渡るか分かりにくい、といった短所がある。ref が渡らない問題は forwardRef で解決できるらしい。
参考記事では、抽象化しすぎるのでほとんど使わないが、Styled Components の withTheme や Redux の connect のように、単純な機能を既存のコンポーネントに足す場合には使ってもよいとしている。作者は導入のメリットはそこまでないとしたうえで、ログ出力などの横断的関心事を扱う、HOC をネストさせない、チームのメンバーが HOC を理解している、の 3 つをすべて満たすなら使ってもよいとしている。
Render Props
Render Props は、コンポーネントが何をレンダリングすべきかを知るために使う、関数型の props である。多くの HOC は Render Props を使った通常のコンポーネントでも実装できる。レンダリングを完全に制御したいときや、レンダリングとロジックを分離したいときに向いていて、特定の箇所だけを再レンダリングできる。一方で、データは render の戻り値の中でしか使えず、重ねるとネストが深くなって読みにくくなる。
作者は再レンダリングを完全に制御したく、非制御コンポーネントは使いたくない場合に使うとよいかもしれない、としている。
Hooks
Hooks を使うと、状態を持ったロジックを、コンポーネントの階層を変えずに再利用できる。Render Props や HOC で起きるラッパー地獄を避けるための仕組みである。分割代入で props の名前を変えられる、何が渡されるか分かりやすい、return の外でもデータを使える、ネストしない、静的型付けがしやすい、といった長所がある。一方で、props 以外からもデータを受け取れて state も持てるので、扱う関心事が増えて関心の分離がしにくい。再レンダリングが起きやすく、パフォーマンスが落ちるおそれもある。
作者は基本的には Hooks でよいとしている。肥大化したらコンポーネントを適宜切り分け、再レンダリングは react-hook-form などで非制御コンポーネントを使って抑える。
参考記事の結論
参考記事の結論は分かれている。可読性や再利用のしやすさなどから Render Props を一押しとし、僅差で Hooks、HOC は使わないほうがよいとする記事がある。可能ならどんな状況でも Hooks を選ぶべきとする記事もある。ほかに、3 つは互いの完全な代替にはならず、Hooks を銀の弾丸として扱うのは間違いで、トレードオフを認識して使うべきとする記事もある。
キーワード
- HOC Pattern
- Render Props
- React Hooks
自分の理解
HOC、Render Props、Hooks の使い分けに悩んでいたところで、ちょうど良い記事を見つけた。