💡

Strapi + Next AuthをNextJS v13 app routingで使う

2023/07/17に公開

TL;DR

  • @/app/providers.tsxSessionProvider を準備
  • それを@/app/page.tsxでbodyタグ内を囲む
  • @/app/signin.tsx@/app/signup.tsxを作りアカウント登録・ログイン ページを用意
  • @/components/Form.tsxを用意して上のページでimportして使う

依存関係のインストール

まず、必要な依存関係をインストールします。これにはstrapi-sdk-jsaxiosnext-authreact-hook-formが含まれます。以下のコマンドを実行してこれらのパッケージをインストールします。

npm install strapi-sdk-js axios next-auth react-hook-form

Strapi SDKの設定

次に、Strapi SDKのインスタンスを作成します。プロジェクトのルートにstrapi.tsという新しいファイルを作成し、以下のコードを追加します。

// strapi.ts
import Strapi from 'strapi-sdk-js';

const strapi = new Strapi({
  url: process.env.STRAPI_URL || 'http://localhost:1337',
  store: {
    key: 'strapi_jwt',
    useLocalStorage: false,
    cookieOptions: { path: '/' },
  },
});

export default strapi;

フックの作成

次に、CRUD操作とユーザー認証を行うためのカスタムフックを作成します。hooksディレクトリを作成し、その中にuseStrapi.tsuseAuth.tsという新しいファイルを作成します。

// hooks/useStrapi.ts
import { useState, useEffect } from 'react';
import strapi from '../strapi';

type DataType = any; // Replace with your data type

export function useStrapi() {
  const [data, setData] = useState<DataType | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);

  const fetchData = async (endpoint: string) => {
    setLoading(true);
    try {
      const response = await strapi.find(endpoint);
      setData(response.data);
      setError(null);
    } catch (err) {
      setError(err as Error);
    } finally {
      setLoading(false);
    }
  };

  const createData = async (endpoint: string, data: DataType) => {
    setLoading(true);
    try {
      const response = await strapi.create(endpoint, data);
      setData(response.data);
      setError(null);
    } catch (err) {
      setError(err as Error);
    } finally {
      setLoading(false);
    }
  };

  const updateData = async (endpoint: string, id: string, data: DataType) => {
    setLoading(true);
    try {
      const response = await strapi.update(endpoint, id, data);
      setData(response.data);
      setError(null);
    } catch (err) {
      setError(err as Error);
    } finally {
      setLoading(false);
    }
  };

  const deleteData = async (endpoint: string, id: string) => {
    setLoading(true);
    try {
      await strapi.delete(endpoint, id);
      setData(null);
      setError(null);
    } catch (err) {
      setError(err as Error);
    } finally {
      setLoading(false);
    }
  };

  return { data, loading, error, fetchData, createData, updateData, deleteData };
}
// hooks/useAuth.ts
import { useState } from 'react';
import { signIn, signOut, useSession } from 'next-auth/client';
import strapi from '../strapi';

export function useAuth() {
  const { data: session, status: loading } = useSession();

  const register = async (username: string, email: string, password: string) => {
    const response = await strapi.register({ username, email, password });
    signIn('credentials', { email, password });
    return response;
  };

  const login = async (identifier: string, password: string) => {
    const response = await strapi.login({ identifier, password });
    signIn('credentials', { identifier, password });
    return response;
  };

  const logout = async () => {
    await strapi.logout();
    signOut();
  };

  return { session, loading, register, login, logout };
}

これらのフックを使用して、Next.jsのコンポーネントでCRUD操作とユーザー認証を簡単に行うことができます。

ログインページの作成

最後に、ログインページを作成します。pages/login.tsxという新しいファイルを作成し、以下のコードを追加します。

// pages/login.tsx
import { Metadata } from 'next'
import { useAuth } from '../hooks/useAuth';
import SignIn from '../components/units/SignIn';

export const metadata: Metadata = {
  title: 'ログイン',
  description: '愛媛県の[西条祭り]を中心に情報を発信しているWEBメディアです。YOIYOI と書いて 良い酔い と読みます 🏮',
}

export default function LoginPage() {
  const { login } = useAuth();

  const handleSignIn = async (data: { email: string; password: string; }) => {
    try {
      await login(data.email, data.password);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <main className="">
      <div className="mx-auto max-w-screen-xl px-4 py-16 sm:px-6 lg:px-8">
        <div className="mx-auto max-w-lg text-center">
          <h1 className="text-2xl font-bold sm:text-3xl">Get started today!</h1>
          <p className="mt-4 text-gray-500">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Et libero nulla
            eaque error neque ipsa culpa autem, at itaque nostrum!
          </p>
        </div>

        <SignIn onSubmit={handleSignIn} />
      </div>
    </main>
  );
}

この修正により、ログインページのコードが大幅に簡素化され、各コンポーネントが再利用可能になります。

以上で、Next.jsとStrapiを使用したユーザー認証の設定は完了です。これにより、Next.jsのアプリケーションでユーザーの登録、ログイン、ログアウトを簡単に行うことができます。

参考元

Discussion