0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[React]カスタムフックについて

Posted at

カスタムフックとは

Reactのカスタムフックは、特定の機能やロジックを分離して再利用可能にすることで、コンポーネントコードの整理に非常に役立ちます。
本記事では、APIからデータを取得するためのカスタムフックを作成し、効率的なデータ取得と表示を実現する方法を紹介します。

カスタムフックの基本概念

Reactのカスタムフックは、特定の処理を他の関数やコンポーネントと分離し、コードの再利用性を高めるための関数です。useStateやuseEffectといったReactのフックを利用することで、カスタムフックは簡単にステートや副作用を管理できます。

たとえば、データ取得のロジックをカスタムフックに移動させると、異なるコンポーネントで同じ取得ロジックを使い回せるようになります。以下は、APIからデータを取得し、その結果やローディング状態、エラーメッセージを管理するカスタムフック useFetchData の例です。

実装例

以下のuseFetchDataは、任意のURLからデータを取得し、コンポーネントに返すための基本的なカスタムフックです。このフックは、データ、ローディング状態、エラーメッセージを含むオブジェクトを返します。

import { useState, useEffect } from "react";

interface FetchDataResult<T> {
  data: T | null;
  isLoading: boolean;
  error: Error | null;
}

export function useFetchData<T>(url: string): FetchDataResult<T> {
  const [data, setData] = useState<T | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true);
      try {
        const response = await fetch(url);
        if (!response.ok) throw new Error("Failed to fetch data");
        const result: T = await response.json();
        setData(result);
      } catch (error) {
        setError(error as Error);
      } finally {
        setIsLoading(false);
      }
    };
    fetchData();
  }, [url]);

  return { data, isLoading, error };
}

useFetchTasksの実装

import { useState, useEffect, useCallback } from "react";
import {
  fetchTasks,
  fetchCompletedTasks,
  fetchUnCompletedTasks,
  fetchInProgressTasks,
} from "@/utils/task-actions";
import { TaskType } from "@/types/task-type";

interface UseFetchTasksResult {
  tasks: TaskType[];
  isLoading: boolean;
  getTasks: () => Promise<void>;
}

export const useFetchTasks = (taskType: string): UseFetchTasksResult => {
  const [tasks, setTasks] = useState<TaskType[]>([]);
  const [isLoading, setIsLoading] = useState<boolean>(true);

  const fetchTaskByType = useCallback(async (type: string): Promise<TaskType[]> => {
    switch (type) {
      case "completed":
        return fetchCompletedTasks();
      case "unCompleted":
        return fetchUnCompletedTasks();
      case "inProgress":
        return fetchInProgressTasks();
      default:
        return fetchTasks();
    }
  }, []);

  const getTasks = useCallback(async () => {
    setIsLoading(true);
    try {
      const fetchedTasks = await fetchTaskByType(taskType);
      setTasks(fetchedTasks);
    } catch (error) {
      console.error("Failed to fetch tasks:", error);
    } finally {
      setIsLoading(false);
    }
  }, [taskType, fetchTaskByType]);

  useEffect(() => {
    getTasks();
  }, [getTasks]);

  return { tasks, isLoading, getTasks };
};

useFetchTasksの動作

taskTypeを切り替えるたびに、フックが自動的に新しいタスクリストを取得しtasksに設定します。
isLoadingでローディング状態を管理し、取得が完了すると一覧が表示されるようにします。

useFetchTasks を使ったコンポーネントの実装

最後に、useFetchTasks を使ってデータを取得し、表示するコンポーネントを作成します。ボタンでタスクの状態を切り替えられるようにしてみましょう。

import { useState } from "react";
import { useFetchTasks } from "@/hooks/useFetchTasks";
import { TaskRow } from "@/components/task-row";
import { Loading } from "@/components/ui/loading";

export default function TaskList() {
  const [taskType, setTaskType] = useState<string>("unCompleted");
  const { tasks, isLoading, getTasks } = useFetchTasks(taskType);

  return (
    <div>
      <button onClick={() => setTaskType("completed")}>Completed Tasks</button>
      <button onClick={() => setTaskType("unCompleted")}>Uncompleted Tasks</button>
      <button onClick={() => setTaskType("inProgress")}>In Progress Tasks</button>

      {isLoading ? (
        <Loading />
      ) : (
        tasks.map((task) => <TaskRow key={task.id} task={task} />)
      )}
    </div>
  );
}

このコンポーネントは、以下のように動作します。

・taskTypeを変更するボタンがあり、それぞれのボタンをクリックすると、異なるタスクリストが取得されます。
・isLoadingを利用して、データ取得中にはローディングインジケーターを表示し、取得後にタスク一覧を表示します。

まとめ

カスタムフックを使うことで、ロジックをコンポーネントから分離し、再利用可能なコードとして保つことができます。
特にデータ取得のような一般的な処理は、カスタムフックにまとめておくことで、コードの見通しがよくなり、保守性も向上します。
Reactアプリケーションでデータ取得をシンプルかつ効率的に実装したい場合、カスタムフックは非常に強力なツールです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?