0Pricing
React Academy · レッスン

HOCからCustom Hookへのリファクタリング

withAuth HOCをuseAuth hookへ段階的に変換します。

「HOCからCustom Hookへのリファクタリング」はCoddyKit上の無料React Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。

ようこそ

このレッスンでは、withAuth HOCをuseAuthカスタムフックに段階的にリファクタリングし、フック版のほうがなぜすっきりしてテストしやすいのかを詳しく確認します。

withAuth HOC(開始時点)

このHOCはコンポーネントを受け取り、ユーザーが認証済みかどうかを確認し、未認証の場合は/loginへリダイレクトします。また、userをpropとして注入します。
function withAuth(Component) {
  return function AuthGuard(props) {
    const { user, loading } = useAuthState();
    if (loading) return <Spinner />;
    if (!user) return <Navigate to="/login" />;
    return <Component {...props} user={user} />;
  };
}

const ProtectedPage = withAuth(MyPage);

HOCの問題点

HOCには次の問題があります。(1) DevToolsにラッパーが追加される、(2) `user` propが暗黙的に注入されるため、コンポーネントがそれを受け取ることを知っていなければならない、(3) HOC全体をレンダリングしないとテストしにくい、(4) 他のフックと簡単に合成できない、という点です。

ステップ1:ロジックをフックに切り出す

HOCにあるすべてのロジックをカスタムフックに移します。フックは認証状態を直接返すため、ラッピングもpropの注入も必要ありません。
function useAuth() {
  const { user, loading } = useAuthState();
  return { user, loading, isAuthenticated: !!user };
}

ステップ2:フックでリダイレクトを処理する

リダイレクトのロジックを別のフック(例:useRequireAuth)に移します。このフックは内部でnavigateを呼び出し、userを返します。
function useRequireAuth(redirectTo = '/login') {
  const { user, loading } = useAuth();
  const navigate = useNavigate();

  useEffect(() => {
    if (!loading && !user) navigate(redirectTo);
  }, [user, loading, navigate, redirectTo]);

  return { user, loading };
}

ステップ3:コンポーネントを更新する

HOCのラッパーを、コンポーネント内での直接的なフック呼び出しに置き換えます。コンポーネントはuseRequireAuthを明示的に呼び出してローディングを処理します。依存関係が見える形になりました。
function MyPage() {
  const { user, loading } = useRequireAuth();
  if (loading) return <Spinner />;
  return <p>Hello, {user.name}</p>;
}

比較したメリット

フック版には次のメリットがあります。(1) DevToolsに余分なラッパーがない、(2) 依存関係が明示的で、コンポーネント内に`useRequireAuth`があることを確認できる、(3) フックをモックしてテストできる、(4) 同じコンポーネント内の他のフックと合成できる、という点です。

フック版のテスト

テストでは、モジュールのエクスポートを置き換えてuseRequireAuthをモックします。コンポーネントのテストでは、コンポーネントをレンダリングして出力を検証するだけで済み、HOCのセットアップは必要ありません。
vi.mock('./useRequireAuth', () => ({
  useRequireAuth: () => ({ user: mockUser, loading: false })
}));

render(<MyPage />);
expect(screen.getByText('Hello, Alice')).toBeInTheDocument();

HOCを残す場合

多くのコンポーネントを宣言的に保護したい場合(例:ルート定義内)や、それぞれにフック呼び出しを追加したくない場合は、HOCを残してください。フックの上にHOCを構築することもできます。
function withAuth(Component) {
  return function (props) {
    const { user, loading } = useRequireAuth();
    if (loading) return <Spinner />;
    return <Component {...props} user={user} />;
  };
}

両方の利点を活かす

最終的な構成は、コンポーネントで直接使うuseRequireAuthフックと、その上に構築した宣言的なルート保護用の薄いwithAuth HOCを用意する形です。どちらも同じフックロジックを共有します。

クイックチェック

withAuth HOCでラップする代わりに、コンポーネント内でuseRequireAuthを呼び出す主なメリットは何ですか?

まとめ

HOCをフックにリファクタリングするには、ロジックをカスタムフックに切り出し、リダイレクトなどの副作用をフックに移し、コンポーネント内でフックを直接呼び出します。宣言的なラッピングが必要な場合は、フックの上に薄いHOCを構築しましょう。

コース修了

おめでとうございます!**Reactパターン:Render PropsとHOC**を修了しました。これで2つの古典的なパターンとそのトレードオフを理解し、現代的なカスタムフックへリファクタリングできるようになりました。

よくある質問

「HOCからCustom Hookへのリファクタリング」レッスンは無料ですか?

はい。「HOCからCustom Hookへのリファクタリング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。

「HOCからCustom Hookへのリファクタリング」で何を学びますか?

withAuth HOCをuseAuth hookへ段階的に変換します。 ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

React Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「HOCからCustom Hookへのリファクタリング」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このReact Academyレッスンでコードを書いて実行できますか?

はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Render Propsパターン
  2. Higher-Order Components(HOC)の基礎
  3. HOC・Render Props・Custom Hooksの比較
  4. HOCからCustom Hookへのリファクタリング
← React Academyに戻る