Higher Order Componentについて調査

はじめに

Higher Order Componentについて学習。
atomic Designと呼ばれるものを実現するよい手法なのだろうと感じ、
使い方を少し学ぼうと思ったので、その記録を。。。

ゴール

  • MyButtonを拡張して、MyCustomButtonコンポーネントをつくる。
    ポイントは、styleをどうやって拡張させることができるのかということである。

MyButtonについて

MyButtonは、赤色の単純なボタンコンポーネントである。

MyButton.jsx

// @flow
import * as React from 'react';

type PropsType = {
  children: React.Element<any>,
  style: Object,
};

// デフォルトstyle情報
const defaultStyle = {
  backgroundColor: 'red',
};

export default function MyButton(props: PropsType): React.Node {
  const { children, style } = props;

  // デフォルトstyleとpropsで指定されたstyle情報を結合
  const Style = {
    ...defaultStyle,
    ...style,
  };

  return (
    <button
      type="button"
      style={Style} 
      {...props}  
    >
      {children}
    </button>
  );
}

defaultスタイルとpropsから渡ってきたsytleを結合するのがポイント。

MyCustomButton

MyCustomButtonは、MyButtonの特徴を受け継ぎながら独自のスタイルをもったボタン。 背景色が青色になり、フォントサイズや文字色のstyle情報が新たに追加される。

MyCustomButton.jsx

// @flow
import * as React from 'react';
import MyButton from './MyButton';

// Enhance関数は、Componentを引数にとり、コンポーネントを返す関数を返す
function Enhance(Component): (Object) => React.Node {
  return props => (
    <Component
      {...props}
      style={{
        backgroundColor: 'blue',
        fontSize: '50px',
        color: 'white',
      }}
    />
  );
}

// HOC
const MyCustomButton = Enhance(MyButton);

export default MyCustomButton;

Enhance関数のように、関数を返す関数は、高階関数(Higher Order function)と呼ばれる。
このHigher OrderであるEnhance関数によりできた新たなコンポーネントこそ
Higer Order Componentということになる。

childrenがpropsに存在するが、HTML要素にchildren属性はつかなく、またMyCustomButton内では、propsをそのまま伝達するだけでよいので感心する。

App.js

ReactDOM.render(
  <div>
    <MyButton>PUSH!!</MyButton>
    <MyCustomButton 
      onClick={() => {console.log('CUSTOM')}} 
    >
      CUSTOM
    </MyCustomButton>
  </div>,
  document.getElementById('root'),
);

各ボタンの表示結果は以下の通り。 MyCustomButtonで追加されているonClickも問題なく動作する。

f:id:poppon555:20180917222359p:plain

気になること

class属性が付与されると、どちらのスタイルが優先されるのだろうか? これについても調べていこう。