React custom hooks

1. カスタムフックとは

カスタムフックはReactにおいて、組み込みのReactフックを使用して独自のロジックを持った独自に作成したフックのことです。カスタムフックを使用することでロジックを再利用可能になります。また、ロジックとビューを分離して実装することができます。

1.1. 命名規則

カスタムフックはuseOnlineStatusのようにuseで始まるキャメルケースで命名する必要があります。リンタが設定されている場合この命名規則が強制されます。

1.2. カスタムフックの中身

カスタムフックはコンポーネントの中のロジック部分を抽出したものです。ですが、ロジックの中で既存のフックを使用していない場合は、カスタムフックとして扱う必要はありません。ロジックを担当する単なる関数とカスタムフックの差は内部でフックを呼び出しているのか、呼び出していないのかにあります。

2. カスタムフックの作り方

公式のコードを使ってカスタムフックのつるり方を説明します。

ネットワークの接続状況を監視するロジックを実装します。カスタムフックを使わない場合は以下のようなコードになります。

import { useState, useEffect } from 'react';

export default function StatusBar() {
  const [isOnline, setIsOnline] = useState(true);
  useEffect(() => {
    function handleOnline() {
      setIsOnline(true);
    }
    function handleOffline() {
      setIsOnline(false);
    }
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

  return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}

ビュー部分とロジック部分が同じコンポーネントに書かれていて責任が分担されていません。また、同じロジックを別の部分で利用したいときにロジック部分をコピペする必要があります。

カスタムフックを実装するためにはコンポーネントの中からロジックを抽出する必要があります。上記のコードのロジック部分は以下です。

const [isOnline, setIsOnline] = useState(true);
  useEffect(() => {
    function handleOnline() {
      setIsOnline(true);
    }
    function handleOffline() {
      setIsOnline(false);
    }
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

この部分を分離してカスタムフックを作成します。

import { useState, useEffect } from 'react';

export function useOnlineStatus() {
  const [isOnline, setIsOnline] = useState(true);
  useEffect(() => {
    function handleOnline() {
      setIsOnline(true);
    }
    function handleOffline() {
      setIsOnline(false);
    }
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);
  return isOnline;
}

さらにこのカスタムフックを使ってビューを実装すると以下のようになります。

import { useOnlineStatus } from './useOnlineStatus.js';

function StatusBar() {
  const isOnline = useOnlineStatus();
  return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}

export default function App() {
  return (
    <>
      <StatusBar />
    </>
  );
}

コンポーネントからロジック部分が分離されてコードの量がかなり削減されました。またロジックが抽象化されたことにより何をしているのかがわかりやすくなっています。

3. カスタムフックを使うメリット

3.1. 再利用性

カスタムフックを利用することで同じロジックを複数回実装するときに何度も同じコードを書く必要がなくなります。

3.2. ロジックの分離

カスタムフックを使ってロジック部分をビューから分離することで責任を分割することができます。

また、コンポーネントを見たときに何をやっているのかを把握しやすくなります。