見出し画像

【React】10分内に「ざっくり」わかる!カスタムフック


はじめに


こんにちは!

今日はカスタムフックについてご紹介します。

カスタムフックを使う理由は大きく3つあります。

ロジックとビュー(コンポーネント)の分離
ロジックを再利用
変更時の対応箇所を局所化

基本的なuseState, useEffect, useContextなどのフックもありますが、細かく自分だけのフックを作って自由度を上げましょう。

本来、コンポーネントの役目は与えられたデータに基づいて画面を構築することですが、ロジックが混在しすぎるとコードが見づらくなります。 そこで、ビューとロジックを分離することで読みやすさを向上させることができます。


例1 : ローカルストレージの値を取得するフック


useLocalStorage カスタムフックを使用してローカルストレージでデータを永続化するシンプルなReactコンポーネントを作成しましょう。

App.jsx

import React from "react";
import useLocalStorage from "./useLocalStorage";

function App() {
  // useLocalStorageカスタムフックを使用してローカルストレージを操作する
  const [age, setAge] = useLocalStorage("age", 32);

  // レンダリング部分
  return (
    // ... 他のJSXコード ...
    <div>
      <h1>カスタムフック</h1>
      <p>{age}</p>
      <button onClick={() => setAge(80)}>年齢設定</button>
    </div>
    // ... 他のJSXコード ...
  );
}

export default App;
  • useLocalStorage カスタムフックを使用して、ローカルストレージ上の "age" キーに対応するデータを取得し、そのデータと更新関数を age および setAge に割り当てます。

  • レンダリング部分では、取得した年齢データを表示し、ボタンをクリックすると年齢を 80 に設定することができます。


useLocalStorage.jsx

import React, { useState, useEffect } from "react";

const useLocalStorage = (key, defaultValue) => {
  // 初回レンダリング時にローカルストレージから値を取得する
  const [value, setValue] = useState(() => {
    const jsonValue = window.localStorage.getItem(key);
    return jsonValue !== null ? JSON.parse(jsonValue) : defaultValue;
  });

  // valueが変更されるたびにローカルストレージに保存する
  useEffect(() => {
    window.localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  // [value, setValue]の形でstateと更新関数を返す
  return [value, setValue];
};

export default useLocalStorage;
  • useLocalStorage カスタムフックは、ローカルストレージにデータを保存するためのものです。

  • useState フックを使用して、初回レンダリング時にローカルストレージからデータを取得します。

  • useEffect フックを使用して、value が変更されるたびにローカルストレージにデータを保存します。

  • 最終的に [value, setValue] の形で現在の値と値を更新するための関数を返します。


例2 : ユーザー情報を取得するAPIフック


App.jsx

import { useState } from 'react';
import { useFetchUsers } from './hooks/useFetchUsers';


// Appコンポーネントを定義します
export const App = () => {
    // useFetchUsersフックを使ってユーザーリスト、ローディング状態、エラー状態、ユーザー情報取得関数を取得します
    const { userList, isLoading, isError, fetchUsers }  = useFetchUsers();

    // レンダリングします
    return (
        <div>
            <button onClick={fetchUsers}>Fetch User</button>
            {isError && <div>何か問題が発生しました...</div>}
            {isLoading ? (
                <div>読み込み中...</div>
            ) : (
                <ul>
                    {userList.map(user => (
                        <li key={user.id}>{user.name}</li>
                    ))}
                </ul>
            )}
        </div>
    );
}

Appコンポーネントでは、useFetchUsersフックを使用してユーザー情報を取得し、その結果を表示します。ユーザー情報の取得は、"Fetch User"ボタンをクリックすることで開始されます。また、取得中は"読み込み中..."と表示し、エラーが発生した場合は"何か問題が発生しました..."と表示します。

useFetchUsers.jsx

// Reactとaxios、useStateとuseCallbackをインポートします
import { useState, useCallback } from 'react';
import axios from 'axios';

// ユーザー情報を取得するカスタムフックを定義します
export const useFetchUsers = () => {
    // ユーザーリスト、ローディング状態、エラー状態を管理するためのステートを定義します
    const [userList, setUserList] = useState([]);
    const [isLoading, setIsLoading] = useState(false);
    const [isError, setIsError] = useState(false);

    // ユーザー情報を取得する非同期関数を定義します
    const fetchUsers = useCallback(async () => {
        // ローディング状態とエラー状態を初期化します
        setIsLoading(true);
        setIsError(false);
        try {
            // axiosを使ってユーザー情報を取得します
            const response = await axios.get('https://example.com/users');
            // 取得したユーザー情報を加工してステートにセットします
            const users = response.data.map(user => ({
                id: user.id,
                name: `${user.first_name} ${user.last_name}`
            }));
            setUserList(users);
        } catch (error) {
            // エラーが発生した場合はエラー状態を更新します
            setIsError(true);
        } finally {
            // 最後にローディング状態を更新します
            setIsLoading(false);
        }
    }, []);

    // ユーザーリスト、ローディング状態、エラー状態、ユーザー情報取得関数を返します
    return { userList, isLoading, isError, fetchUsers };
}

このコードはReactとaxiosを使用してユーザー情報を取得し、その情報を表示するためのものです。まず、useFetchUsersというカスタムフックを定義しています。このフックは、ユーザー情報を取得する非同期関数fetchUsersと、その結果を管理するためのステート(userList、isLoading、isError)を提供します。

fetchUsers関数は、axiosを使用してユーザー情報を取得し、その結果をuserListステートにセットします。また、この関数はローディング状態とエラー状態も管理します。ユーザー情報の取得を開始すると、isLoadingをtrueにセットし、取得が完了するとfalseに戻します。また、取得中にエラーが発生すると、isErrorをtrueにセットします。


最後に


カスタムフックの導入により、Reactコンポーネントの開発が効果的になります。まず、ビューとロジックの明確な分離により、コードの可読性が向上し、保守性が向上します。例えば、ローカルストレージの値を取得するカスタムフックやAPIからユーザー情報を取得するフックのように、共通のロジックを再利用できます。これにより、コンポーネントが単純でシンプルな形になり、変更が必要な場合も局所的に対応できます。

さらに、カスタムフックの利用は柔軟性を提供します。既存のuseStateやuseEffectなどの基本的なフックに加えて、プロジェクトに特有のロジックやデータの操作に対応するカスタムフックを自由に作成できます。これにより、開発者はより高度な制御を得られ、コンポーネントの再利用性とメンテナビリティが向上します。総じて、カスタムフックの利用はReactアプリケーションの開発をより効率的かつ洗練されたものにします。



向上心のエンジニア
ソンさん



【参考】



この記事が気に入ったらサポートをしてみませんか?