👨‍🏫

ReactのカスタムHookを使ってみる

2023/07/01に公開

一応状態管理らしい

同じファイルにuseStateを書き過ぎるとコードが増えすぎてしまう!
この辺は、FlutterのStatefulWidgetに似てる気がします。できるだけUIとロジックは分離したいので、オブジェクト思考プログラミングらしくするために、ファイルを分けて、APIからデータが取得できるか試してみました。

✅元のコード

なんだか冗長なコードですね。長いって意味ですね。僕は国語が弱いので、知りませんでした😅

import { useState, useEffect } from "react";

function App() {
  // データの型を定義するinterfaceを作成
  interface Data {
    id: number;
    name: string;
  }

  // Data型の配列を作成
  const [data, setData] = useState<Data[]>([]);
  // JSONPlaceholderからデータを取得する関数
  const getData = async () => {
    // JSONPlaceholderからデータを取得
    const response = await fetch("https://jsonplaceholder.typicode.com/users");
    // 取得したデータをJSON形式に変換
    const data = await response.json();
    // 変換したデータを変数に格納
    setData(data);
  };
  // コンポーネントがマウントされた時に実行する関数
  // マウントとは、コンポーネントがDOMに追加されること
  // アンマウントは、コンポーネントがDOMから削除されること
  useEffect(() => {
    getData();
  }, []);// []は第二引数で、空の配列を渡すことで、コンポーネントがマウントされた時のみ実行されるようになる
  // 取得したデータを表示する

  return (
    <>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </>
  );
}

export default App;

🔧リファクタリングしてみる

Udemy何度もやったのに、Reactのロジックを分けるところが理解できませんでした!
なので、ChatGPTくんに手伝ってもらいました!

🤖ChatGPT

状態管理とファイルの分離を実現するために、以下のステップに従ってコードをリファクタリングします。

状態管理のためのカスタムフックを作成します。
ロジック部分を別のファイルに分離します。
画面部分を別のファイルに分離します。
まず、状態管理のためのカスタムフックを作成しましょう。useDataという名前のカスタムフックを作成し、状態とデータの取得関数を含めます。

import { useState, useEffect } from "react";

interface Data {
  id: number;
  name: string;
}

const useData = () => {
  const [data, setData] = useState<Data[]>([]);

  const getData = async () => {
    const response = await fetch("https://jsonplaceholder.typicode.com/users");
    const data = await response.json();
    setData(data);
  };

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

  return { data };
};

export default useData;

次に、ロジック部分を別のファイルに分離します。useDataカスタムフックを使用してデータを取得し、AppLogicという名前のファイルにロジックを移動します。

import useData from "./useData";

const AppLogic = () => {
  const { data } = useData();

  return { data };
};

export default AppLogic;

最後に、画面部分を別のファイルに分離します。AppコンポーネントをAppScreenという名前のファイルに移動します。

import AppLogic from "./AppLogic";

const AppScreen = () => {
  const { data } = AppLogic();

  return (
    <>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </>
  );
};

export default AppScreen;

これで、状態管理と画面ロジックが別々のファイルに分離されました。元のコードではAppコンポーネントでしたが、これをAppScreenという名前に変更しました。そして、新しいAppコンポーネントを作成して、AppScreenを含めます。

import AppScreen from "./AppScreen";

function App() {
  return <AppScreen />;
}

export default App;

このようにリファクタリングすることで、状態管理と画面のロジックが分離され、コードがよりモジュール化された状態になります。

スクリーンショット

状態管理のパッケージについて質問してみた

はい、RecoilやReduxなどの外部の状態管理ライブラリを使用せずに、状態管理を実装することも可能です。ReactのHooksを使用することで、状態を管理するためのローカルなステートを作成できます。

ReactのHooksには、useStateやuseReducerなどの関数があります。これらの関数を使用することで、コンポーネント内で状態を保持し、更新することができます。

このように、Hooksを使用することで、コンポーネント内で状態を管理することができます。このアプローチは、小規模なアプリケーションや状態が単純な場合に特に有用です。ただし、アプリケーションが複雑化し、複数のコンポーネント間で状態を共有する必要がある場合は、外部の状態管理ライブラリ(例:Recoil、Redux)の使用を検討することが一般的です。これらのライブラリは、状態の中央管理やデータフローの制御など、より高度な機能を提供します。

まとめ

やはり、Riverpodみたいに状態管理のパッケージを使うのが他の言語でも当然みたいですね。使ってないところもあるらしいですが?
ChatGPT3.5を使えば、ReactとTypeScriptのキャッチアップは、早くできるかもしれません?
私の師匠は、C++を早くキャッチアップしたらしい?

Discussion