React チュートリアル【カスタムフック】
#React

カスタムフック


カスタムフックとは

  • ただの関数
  • hooksの各機能を使用できる
  • コンポーネントからロジックを分離していく考え方
  • メリットとして使い回しがきく、テストが容易、見通しが良くなる等がある
  • 自由に作成できる。暗黙のルールでuse~という命名にする


./hooks/useAllUsers.ts

import axios from "axios";

import { useState } from "react";
import { UserProfile } from "../types/userProfile";
import { User } from "../types/api/user";

// 全ユーザー一覧を取得するカスタムフック
export const useAllUsers = () => {
 const [userProfiles, setUserProfiles] = useState<Array<UserProfile>>([]);
 const [loading, setLoading] = useState(false);
 const [error, setError] = useState(false);

 const getUsers = () => {
  setLoading(true);
  setError(false);

  axios
   .get<Array<User>>("https://jsonplaceholder.typicode.com/users")
   .then((res) => {
    const data = res.data.map((user) => ({
     id: user.id,
     name: `${user.name}(${user.username})`,
     email: user.email,
     address: `${user.address.city}${user.address.suite}${user.address.street}`
    }));
    setUserProfiles(data);
   })
   .catch((err) => {
    setError(true);
   })
   .finally(() => {
    setLoading(false);
   });
 };

 // 他のコンポーネントでカスタムフックで定義したStateや関数が使用できるように、returnで返却する
 return { getUsers, userProfiles, loading, error };
};


./App.tsx

import "./styles.css";

import { UserCard } from "./components/UserCard";
import { useAllUsers } from "./hooks/useAllUsers";

export default function App() {
 // カスタムフックを呼び出し、返却値を受け取る
 const { getUsers, userProfiles, loading, error } = useAllUsers();
 const onClickFetchUser = () => getUsers();

 return (
  <div className="App">
   <button onClick={onClickFetchUser}>データ取得</button>
   <br />
   {error ? (
    <p style={{ color: "red" }}>データの取得に失敗しました</p>
   ) : loading ? (
    <p>Loading...</p>
   ) : (
    <>
     {userProfiles.map((user) => (
      <UserCard key={user.id} user={user} />
     ))}
    </>
   )}
  </div>
 );
}


まとめ

カスタムフックはhooksというディレクトリを切って管理していくのが一般的である。
他のコンポーネントでカスタムフックで定義したStateや関数が使用できるように、returnで返却する。
カスタムフックで呼び出したStateはそれぞれのコンポーネントで独立扱いなので、コンポーネント間でStateは競合しない。