3行で
- Reactを使ってる
- あるReactコンポーネントの下に多種のボタンが入るようなのを作りたかった
- HOCを知った
HOCとは
Higher Order Component の略。
公式ドキュメントはここ。
A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature.
(意訳:HOCはReactでのコンポーネント再利用の進んだテクニックです。HOCは、それ自体はReact APIの一部ではありません。それらはReactの構成上の性質から生まれるパターンです。)
とのこと。
Concretely, a higher-order component is a function that takes a component and returns a new component.
(意訳: 具体的には、HOCは一つのコンポーネントを取って一つの新しいコンポーネントを返す関数です。)
なるほど。ドキュメントの最初の方に書かれているこれを見るだけでとてもわかりやすい。
const EnhancedComponent = higherOrderComponent(WrappedComponent);
やってみる
なんとなくわかったところで、やってみます。
ボタンの種類を渡すとそのボタンを埋め込んだ特定のコンポーネントを返してくれるHOC
さて、今回必要だったのはボタンの種類を渡すとそのボタンを埋め込んだ特定のコンポーネントを返してくれるHOCです。つまりこんな感じでしょうか。
const UserComponentWithSpecialbutton = embedButtonInUserComponent(SpecialButton)
HOCで実装
使い方はなんとなくイメージできたので、ちゃんと書いていきます。Flowを使っているのでこういう感じになります。 1
// @flow
type User = {
id: number,
name: string,
};
type Props = {
user: User
}
// この関数がHOC
// この場合は状態を持たないコンポーネント(いわゆるSFC)を返している
const embedButtonInUserComponent = (ButtonComponent: React.ComponentType<Props>) => {
return (props: Props) => {
return (
<div className="user">
<div className="user__name">
<a href={`/users/${props.user.id}`}>{props.user.name}</a>
</div>
<div className="user__button">
<ButtonComponent user={props.user} />
</div>
</div>
)
}
}
export default embedButtonInUserComponent;
HOCを使ってコンポーネントを作成
const UserComponentWithSpecialButton = embedButtonInUserComponent(SpecialButton);
export default UserComponentWithSpecialButton;
作成したコンポーネントを利用
<UserComponentWithSpecialButton user={user} />
UserComponentWithXXXButtonみたいなものをそれぞれ作ってこういう感じで使える。
雑感
- HOCはパターンとしての制約というか、こうやって書けよという方針がReactのドキュメントにきちんと書かれている
- 特別な関数なので、
hocs/
みたいな専用ディレクトリを切って管理していいのではないかと思うけどみんなどうやってるのか気になる- ググって出てきたredditのスレッド In which folder should i put higher order components? : reactjsでは、
helpers/
に置いている、という人も。
- ググって出てきたredditのスレッド In which folder should i put higher order components? : reactjsでは、
-
Flowでこれ系の型を書くときは
ComponentType
というのを使うらしい。詳細はHigher-order Components | Flowに書かれていた。 ↩