Yanonoblog!

こつこつと

カスタムフック

はじめに

本記事では「モダンJavaScriptの基本から始める React実践の教科書」で学んだ内容と別途気になって調べた内容や知識も含めアウトプットしています。

書籍に記載されている内容を順序立ててまとめるというよりは、整理しておきたい周辺の知識と深ぼった内容を雑多に書いています。

カスタムフック

Reactの提供するフック機能(useState, useEffectなど)を組み合わせて作成された、再利用可能な関数です。

コンポーネント内で状態やライフサイクル、そしてその他のReactのフックを利用できるように設計されています。

定義方法

カスタムフックは普通のJavaScript関数と同じように定義できます。

カスタムフックの名前は "use" で始まるべきです。

このルールに従うことで、ReactやLinterがフックのルール違反を検出できるようになります。

下記はウィンドウの幅を返す独自のフック useWindowWidth です。

import { useState, useEffect } from 'react';

// ウィンドウの幅を返すuseWindowWidthフック
const useWindowWidth = () => {
  // 現在のウィンドウの幅を保持するためのステートを定義
  // 初期値として現在の window.innerWidth を設定
  const [windowWidth, setWindowWidth] = useState(window.innerWidth);

  // ウィンドウの幅が変わったときに新しいウィンドウの幅をステートにセットする関数を定義
  const handleResize = () => {
    setWindowWidth(window.innerWidth);
  }

  // useEffect フックを使って、コンポーネントがマウントされた時と更新された時のイベントリスナーを設定します
  useEffect(() => {
    // 'resize'イベントに対し handleResize関数をリスナーとして設定
    window.addEventListener('resize', handleResize);

    // クリーンアップ関数
    // コンポーネントがアンマウントされるとき、または依存関係が変更されるときに実行
    return () => {
      window.removeEventListener('resize', handleResize);
    }
  }, []);
  // カスタムフックの戻り値としてウィンドウの幅を返す
  return windowWidth;
}

export default useWindowWidth;

クリーンアップ関数とは

アンマウントされるときにイベントリスナを削除する関数のことです。

useEffectの中で関数を返すと、その関数はクリーンアップ関数となります。

ReactのuseEffectフックでは、コンポーネントのライフサイクルに連動した副作用(サイドエフェクト)の管理を行うことができます。これには、外部リソースへのサブスクリプションや非同期操作、そしてDOMの操作などが含まれます。

useEffectフック内で定義された関数は、コンポーネントレンダリングされた直後に実行されます。この関数が別の関数を返す場合、その返された関数はクリーンアップ関数と呼ばれます。

クリーンアップ関数呼び出されるタイミング
  1. コンポーネントがアンマウント(画面から削除)されるとき
  2. 同じuseEffectフックが再度実行される直前

クリーンアップ関数の主な役割は、前回のuseEffectによって設定された副作用(例えばイベントリスナなど)をクリーンアップ(削除)することです。

これにより、不要になったリソースを解放し、メモリリークを防ぐことができます。

一度実行した処理が動き続けているとバグやメモリに多大な負荷を与えてしまうので、クリーンアップ関数が存在するようです。

カスタムフックを使用する

下記は先程定義したカスタムフックを実際に使用する例です。

import React from 'react';
import useWindowWidth from './useWindowWidth';

const ShowWindowWidth = () => {
  const width = useWindowWidth();

  return (
    <div>
      <h2>Window width is: {width}px</h2>
    </div>
  );
}

export default ShowWindowWidth;

上記のように再利用可能なカスタムフックを使うことでコードがシンプルとなり見通しが良くなりました。

メリット

再利用性

カスタムフックは、コードの再利用性を大幅に向上させます。同じロジックを必要とするさまざまなコンポーネント間でフックを共有することができます。

分離性

カスタムフックを用いることで、コンポーネントから複雑なロジックを抽出し、テストや理解を容易にします。

可読性

カスタムフックを用いると、コンポーネント内のロジックが整理され、その結果、コードの可読性が向上します。

ディレクトリ構成の例

カスタムフックは、プロジェクトのディレクトリ構成における特定の場所に配置されるわけではなく、そのプロジェクトの構成やチームの規約によって変わります。

一般的には下記のようにすべてのカスタムフックを一箇所にまとめ、それらを再利用しやすくした構成が多く見受けられます。

.
├── src/
│   ├── features/
│   │   ├── Users/
│   │   │   ├── index.tsx
│   │   │   ├── UserList.tsx
│   │   │   ├── UserDetails.tsx
│   │   │   └── userService.ts
│   │   └── Products/
│   │       ├── index.tsx
│   │       ├── ProductList.tsx
│   │       ├── ProductDetails.tsx
│   │       └── productService.ts
│   ├── hooks/
│   │   ├── useWindowSize.ts
│   │   └── useAuth.ts
│   ├── App.tsx
│   └── index.tsx
├── package.json
└── tsconfig.json

まとめ

Reactのカスタムフックは、コードの再利用、可読性の向上、そしてテストの容易性というメリットを提供します。

カスタムフックをうまく活用することで、よりきれいで、管理しやすいコードを書くことができます。

それぞれのフックは独立した関数であるため、他のフックやコンポーネントと独立してテストすることが可能です。

また、必要に応じてフックを組み合わせることで、より複雑な機能を持つ新しいフックを作成することも可能です。

参考

続く…

コメント

本記事の内容は以上になります!

書籍の続きのアウトプットも随時更新したいと思います。


プログラミングスクールのご紹介 (卒業生より)

お世話になったプログラミングスクールであるRUNTEQです♪

https://runteq.jp/r/ohtFwbjW

こちらのリンクを経由すると1万円引きになります。

RUNTEQを通じて開発学習の末、受託開発企業をご紹介いただき、現在も双方とご縁があります。

もし、興味がありましたらお気軽にコメントか、TwitterのDMでお声掛けください。

https://twitter.com/outputky