Supabase × Next.jsでログイン認証を実装する(カスタムフックで簡略化)

Supabase × Next.jsでログイン認証を実装する(カスタムフックで簡略化)

投稿日: 2025年03月19日

学習振り返り
要約
  • Supabaseを用いたログイン認証のチェック処理をカスタムフック(useAuthCheck)に切り出し、コードを簡潔化した。
  • 未ログインユーザーがページに直接アクセスした場合、自動的にログインページへリダイレクトする機能を実装。
  • カスタムフックの導入により、認証処理の再利用性が向上し、状態管理と可読性が改善された。

個人開発で Supabaseを使用したログイン認証 を実装している中で、ログインが完了していないユーザーがURLを直接入力してページにアクセスした場合、適切にリダイレクトさせる処理。ブログ作成の課題で実装した箇所かなと思います!

最初はフロント側で useEffect を用いて supabase.auth.getUser() を実行し、ログインユーザーをチェックしていましたが、この処理を カスタムフックに切り出すことで、より簡潔で再利用可能なコードにリファクタリング しました!


1. 目次

  1. ログイン認証の基本処理

  2. カスタムフックを使用して簡略化

  3. カスタムフックの実装

  4. まとめ


2. ログイン認証の基本処理

元々使用していたコードでは useEffect を使ってログインユーザーの情報を取得し、未ログインであれば /login にリダイレクトする処理を実装していました。

🥑 既存のログインチェック処理

import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { supabase } from "@/lib/supabaseClient"; // Supabaseの設定

export default function ItemListPage() {
  const [user, setUser] = useState(null);
  const router = useRouter();

  useEffect(() => {
    const authUser = async () => {
      const {
        data: { user },
      } = await supabase.auth.getUser();

      if (!user) {
        router.push("/login");
        return;
      }

      setUser(user);
    };

    authUser();
  }, [router]);

  return (
    <div>
      <h1>アイテムページ</h1>
      {user ? <p>ようこそ, {user.email}</p> : <p>ロード中...</p>}
    </div>
  );
}

🥑 このコードの問題点

  • ページごとに同じ認証処理を記述する必要がある

  • ロジックが散らばるため、管理が大変

  • リダイレクトの処理が増えると可読性が落ちる


3. カスタムフックを使用して簡略化

これらの問題を解決するために、カスタムフック (useAuthCheck) を作成して、認証処理を再利用可能にしました。

🙉 改善後のコード

import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { useAuthCheck } from "@/hooks/useAuthCheck";

const ItemListPage = () => {
  const [user, setUser] = useState(null);
  const authUser = useAuthCheck(); // カスタムフックでユーザー情報を取得

  useEffect(() => {
    if (authUser) {
      setUser(authUser);
    }
  }, [authUser]);

  return (
    <div>
      <h1>アイテムページ</h1>
      {user ? <p>ようこそ, {user.email}</p> : <p>ロード中...</p>}
    </div>
  );
}

export default ItemListPage;

🙉 改善後のポイント

カスタムフックを導入してコードを簡潔に
複数ページで同じ認証処理を使い回せる
状態管理がしやすく、可読性が向上


4. カスタムフックの実装

では、実際に useAuthCheck のカスタムフックを作成しましょう。

/hooks/useAuthCheck.ts

import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { supabase } from "@/lib/supabase";
import { User } from "@supabase/supabase-js";

const useAuthCheck = () => {
  const [user, setUser] = useState<User | null>(null);
  const router = useRouter();

  useEffect(() => {
    const checkUser = async () => {
      try {
        const { data, error } = await supabase.auth.getUser();

        if (error || !data?.user) {
          console.error("認証エラー:", error?.message || "ユーザーが未ログイン");
          router.replace("/login"); // `replace` にすることでブラウザ履歴を変更
          return;
        }

        setUser(data.user);
      } catch (err) {
        console.error("ユーザー情報の取得に失敗しました:", err);
        router.replace("/login");
      }
    };

    checkUser();
  }, [router]);

  console.log("🐧🐧🐧🐧 ~ useAuthCheck ~ user:", user);

  return user;
};

export default useAuthCheck;

5. まとめ

フロントエンドでSupabase の auth.getUser() を使い、ログインユーザーをチェック
未ログインユーザーがページに直接アクセスした場合は、ログインページへリダイレクト
カスタムフック (useAuthCheck) を作成し、認証処理を簡潔化&再利用性を向上

Supabase × Next.js を使ったログイン認証の処理を整理し、より使いやすい形にリファクタリング することができました!

シェア!

Threads
Loading...
記事一覧に戻る
Threads
0