はじめに
最近、supabaseという便利なものを見つけたので少し使ってみました!今回は認証だけ使っています。
今回のコード↓
https://github.com/NozomuTsuruta/next-supabase-auth-example
supabaseとは
Firebaseのようにデータベースや認証を簡単に使えるサービスです。データベースはFirebaseはNoSQLなのに対し、supabaseはPostgreSQLが採用されています。個人的に新しく覚えることが少なくてわかりやすいです。比較的新しいのでFirebaseほどたくさんの機能はありませんが、今後どんどん追加されていくみたいです。
導入
まずはインストールします。
## npm
npm install @supabase/supabase-js
## yarn
yarn add @supabase/supabase-js
https://app.supabase.io/にアクセスして、アカウントを作成し、新しいプロジェクトを作成します。
作成した後、そのプロジェクトを開き、SettingsのAPIのページに行くと、URLとAPI_KEYS(public)があると思います。
それをコピーして、next.config.js
に追加します。
module.exports = {
env: {
SUPABASE_URL: "[URL]",
SUPABASE_KEY: "[PUBLIC_API_KEY]",
},
};
実際に使ってみる
supabaseの設定ファイル
下のように先ほどnext.config.js
に追加した値をここで使います。
import { createClient } from "@supabase/supabase-js";
export const supabase = createClient(
process.env.SUPABASE_URL as string,
process.env.SUPABASE_KEY as string
);
あとは、src/util/supabase.ts
からsupabase
をインポートして簡単に使えます。
Formコンポーネント
いろんなページで使う用に作ります。
import { FC } from "react";
type IProps = {
onSubmit: any;
buttonText: string;
inputList: {
name: string;
ref: any;
type: string;
}[];
};
export const Form: FC<IProps> = ({ onSubmit, buttonText, inputList }) => {
return (
<form onSubmit={onSubmit}>
{inputList.map((props) => (
<label key={props.name}>
<span>{props.name}</span>
<input {...props} />
</label>
))}
<button type="submit">{buttonText}</button>
</form>
);
};
それぞれのページを簡単に作っていきます。react-hook-formを使っているので使い方がわからない方はみてみてください!
react-hook-formの使い方を解説 v6.13.0 useController追加!
サインインページ
import { NextPage } from "next";
import { useForm } from "react-hook-form";
import { Form } from "../components/Form";
import { supabase } from "../util/supabase";
type IForm = {
email: string;
password: string;
};
const Signin: NextPage = () => {
const { register, handleSubmit } = useForm<IForm>();
const handleSignin = ({ email, password }: IForm) => {
supabase.auth.signIn({ email, password });
};
const inputList = [
{ type: "email", name: "email", ref: register },
{ type: "password", name: "password", ref: register },
];
return (
<Form
onSubmit={handleSubmit(handleSignin)}
inputList={inputList}
buttonText="サインイン"
/>
);
};
export default Signin;
サインアップページ
サインアップ後にそのまま登録するか、メールアドレス確認するかどうかはsupabaseで設定できます。
import { NextPage } from "next";
import { useForm } from "react-hook-form";
import { Form } from "../components/Form";
import { supabase } from "../util/supabase";
type IForm = {
email: string;
password: string;
passwordConf: string;
};
const Signup: NextPage = () => {
const { register, handleSubmit } = useForm<IForm>();
const handleSignup = ({ email, password }: IForm) => {
supabase.auth.signUp({ email, password });
};
const inputList = [
{ type: "email", name: "email", ref: register },
{ type: "password", name: "password", ref: register },
{ type: "password", name: "passwordConf", ref: register },
];
return (
<Form
onSubmit={handleSubmit(handleSignup)}
inputList={inputList}
buttonText="サインアップ"
/>
);
};
export default Signup;
パスワード再設定ページ
resetPasswordForEmail
の引数にとったメールアドレスに再設定用のメールが送信されます。
import { NextPage } from "next";
import { useForm } from "react-hook-form";
import { Form } from "../components/Form";
import { supabase } from "../util/supabase";
type IForm = {
email: string;
};
const Forgot: NextPage = () => {
const { register, handleSubmit } = useForm<IForm>();
const handleResetPassword = ({ email }: IForm) => {
supabase.auth.api.resetPasswordForEmail(email);
};
const inputList = [{ type: "email", name: "email", ref: register }];
return (
<Form
onSubmit={handleSubmit(handleResetPassword)}
inputList={inputList}
buttonText="パスワード再設定メール送信"
/>
);
};
export default Forgot;
ログイン後のページ
import { NextPage } from "next";
const Home: NextPage = () => {
return <h1>Hello</h1>;
};
export default Home;
_app.tsx
onAuthStateChange
でログイン状態を監視できます。簡単にルーティングも実装しました。
import { AppProps } from "next/app";
import { supabase } from "../util/supabase";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
export default function App({ Component, pageProps }: AppProps) {
const { pathname, push } = useRouter();
const [loading, setLoading] = useState(true);
supabase.auth.onAuthStateChange((_, session) => {
if (session?.user && (pathname === "/signin" || pathname === "/signup")) {
push("/");
} else if (!session?.user && pathname !== "/signup") {
push("/signin");
}
});
useEffect(() => {
(async () => {
const user = supabase.auth.user();
if (user && (pathname === "/signin" || pathname === "/signup")) {
await push("/");
} else if (!user && pathname !== "/signup") {
await push("/signin");
}
setLoading(false);
})();
}, []);
return (
<>
{loading ? (
<h1>loading...</h1>
) : (
<>
<button onClick={() => supabase.auth.signOut()}>ログアウト</button>
<Component {...pageProps} />
</>
)}
</>
);
}
今回のコード↓
https://github.com/NozomuTsuruta/next-supabase-auth-example
終わりに
ここまで読んでいただきありがとうございます!今回CSSを書かなかったので見た目はだいぶ酷いと思います🙇♂️
今回データベースの方は使いませんでしたが、とても便利なので使ってみてください!