🍯

【React入門】カスタムフックを作ろう

2021/10/01に公開

カスタムフックとは

React 16.8以降で利用できるReactフックの機能には、useStateuseEffectなど用途が決まったものがあります。
カスタムフックとは、自分で作ったフックのことです。
再利用できる独自の関数を作ることで、コンポーネントからロジックを切り離すことが可能になり、また記述量も削減できます。

自分でフックを作るというとハードルが高く感じられるかもしれませんが、最初から難しいものを作成する必要はありません。
以下では、簡単なコンポーネントをカスタムフックで書いてみた例を紹介します。

作ってみよう

下記はボタンを押すとモーダルが開閉するコンポーネントを、カスタムフックを使わず作りました。CSSはお好みで調整してください。

const App = () => {
  // モーダル開閉状態state
  const [modalStatus, setModalStatus] = useState(false);

  // モーダルを開く
  const openModal = () => {
    setModalStatus(true);
  };

  // モーダルを閉じる
  const closeModal = () => {
    setModalStatus(false);
  };
 
  return (
  <>
    <div>
      <button onClick={() => openModal()}>
        Open
      </button>
    </div>
    <MenuComponent 
     modalStatus={modalStatus}
     closeModal={closeModal}
    />
    </>
  );
 }

const ModalComponent = ({setModalStatus, closeModal}) => {
  if (!modalStatus) return null;
  
  return (
      <div>
        <p>ここはコンテンツです。</p>
	 <button onClick={() => closeModal()}>
          Close
         </button>
      </div>
  )
}

これだとロジックとUI部分が混在していて読みづらく、同じようなコンポーネントを作成するたびにuseStateと開閉の関数を定義することになります。
複雑なロジックや複数のstateを使用する場合、さらにややこしくなってしまいます。

カスタムフックで書いてみよう

ロジックの部分だけカスタムフックに切り離します。
作成するときのルールは、他のReact Hooksと同じようにuseXXXの関数名で作成します。

const useModal = () => {
  // モーダル開閉状態state
  const [modalStatus, setModalStatus] = useState(false);

  // モーダルを開く
  const openModal = () => {
    setModalStatus(true);
  };

  // モーダルを閉じる
  const closeModal = () => {
    setModalStatus(false);
  };

 // useModalの戻り値はstateと関数
  return {
    modalStatus,
    closeModal,
    openModal,
  };
}

次に作成したuseModal()をUI部分に呼び出して使用します。

const App = () => {

  // useModalカスタムフックを呼び出す
  // 呼び出したカスタムフックは好きな名前を付けることができる
 const modalStore = useModal();
  const { modalStatus, closeModal, openModal } = modalStore;
 
  return (
  <>
    <div>
      <button onClick={() => openModal()}>
        Open
      </button>
    </div>
    <MenuComponent 
     modalStatus={modalStatus}
     closeModal={closeModal}
    />
    </>
  );
 }

const ModalComponent = ({setModalStatus, closeModal}) => {
  if (!modalStatus) return null;
  
  return (
      <div>
        <p>ここはコンテンツです。</p>
	 <button onClick={() => closeModal()}>
          Close
         </button>
      </div>
  )
}

上記の例ではあまり変わらないように見えますが、複雑なロジックの時に本領を発揮します。
useModal()を一度定義しておけば、別のコンポーネントでも使いまわすことができるので、いちコンポーネント内でのロジックの記述は2行のみになります。
また、ロジックとUIが分離されていてコードの見通しが良くなりました。

同じカスタムフックを別のコンポーネントで使用しても、stateは共有されることはありません。あくまでカスタムフックは、ロジックを共有するためのものなので、使用する場所ごとにstateは独立しています。

まとめ

今回は、簡単なコンポーネントをカスタムフックに書き換える例を紹介しました。
深く考えずにまずは「コードが複雑になってきたからカスタムフックを作ってみよう」ぐらいの気持ちから始めて、慣れきたらより難しい使い方でやってみるといいと思います。

最後まで読んでいただきありがとうございました。

Discussion