📝はじめに
学習の目的
未経験からエンジニアを目指す中で、学習のアウトプットとして本記事を作成しました。現在は TypeScript や React、Next.js を中心に学んでおり、それらを用いた実装を主に投稿していく予定です。
記事の内容について
本記事では、Supabase の Auth 機能を使ってユーザー認証を行い、ログイン中のユーザーのプロフィール情報(氏名やメールアドレス)を取得して画面に表示するマイページを実装します。
🔧 使用技術・環境
- Next.js (App Router, TypeScript)
- Supabase(Authentication + Database)
🛠 Supabase側の準備
- Supabase プロジェクトを作成
-
profiles
テーブルを作成(カラム:id
,full_name
,email
)-
id
はuuid
型で、auth.uid()
をデフォルト値に設定(GUI上で "Default value" にauth.uid()
を指定※こちらは後述しています。)
-
- RLS(Row Level Security)を一時的に無効化(※次回以降で設定)
🔐 ユーザー登録(開発用の仮ユーザー)
開発デモを投稿する上でダミーアドレスに実際のメールが来ても開けないからログインができない"(-""-)"
ということで"auth.admin.createUser()を使います!この関数はsupabaseの管理者権限(service_role_key)を使って以下のようなことができる。
- サーバー側から登録ができる
- email_confirm: true で省略できる
- service_role_keyで強い操作が可能
実際にやってみる。
①/app/dev-signup/page.tsxを作成する。
その中にこのように記載した。
なぜ auth.admin.createUser()
を使うのか?
通常の signUp
では「仮登録 → メールリンクをクリック → 本登録」という流れが必要。
しかし今回のようにメールを実際に確認できないダミーユーザーを使いたい場合は不便( ;∀;)
そのため、管理者権限(service_role_key
)を使い auth.admin.createUser()
を呼び出すことで、
- サーバー側からのユーザー作成
-
email_confirm: true
によりメール確認をスキップ
つまり「管理者が信頼して登録したユーザーだから、本人確認済みと見なすよ~」という扱いになります。
これは 管理者だけが持つ特別な権限なので、一般ユーザーが使うことはできません。注意が必要です!
これでlocalhostにて動作確認...登録成功。ちゃんとsupabaseにも反映されてるかな??
できてる!(∩´∀`)∩
②ログイン機能を作る
app/login/page.tsxを作成してログイン処理を実装する。
- 9行目からuseStateを使って画面に入力されたemailとpasswordを管理する。
- async,awaitを用いて非同期処理で実装。ちゃんと情報を入手してから先に進もうね!
- errorならメッセージを表示する。エラーじゃなければ/mypageにページ遷移してね!
- returnの後ろにUIを書いていく。今回はとてもシンプルなUIで。
👤 マイページでプロフィールを表示
ログインフォームの作成ができたから次は遷移先のマイページを作成してみる。
/app/mypage/page.tsxを作成。
- useEffectを使ってページが開いたときにプロフィールが取得できるように記載した。
- fetchProfileの関数の中でasync,awaitで非同期処理を定義。
- supabase.auth.getUser()を使って現在のユーザー情報を取得する。その戻り値からuserオブジェクトを取り出す。
- if(user)でuserが存在、つまり”ログインしている”ならそのデータを取得して、nullの場合はスキップされる。
- !error && dataではエラーが発生していない、dataが正常に取得できた(null)じゃない、この2点がそろっているときsetProfile関数を呼び出すことでプロフィールデータを状態変数に保存する。
- fetchProfile()を呼び出してプロフィール情報を実際に取得してもらう。今回のコードでは依存配列が[](空配列)となっているので最初のレンダリング時に実行。再レンダリング時には実行されない。
- 以下returnでUIを記載。
💡 補足
エラーが出ていないことと data が正常に取得できていること。これって同じことじゃないの?と思ったので補足します。
実は「エラーにはならないけど、データ自体は取得できていない」というケースがあります。
具体的には:
- ユーザーはログインしているけど、
profiles
テーブルに該当ユーザーの行が存在しない- Supabase 側の制約や RLS の設定でデータ取得が制限されている
このように「データが取得できなかった」=「エラーが発生している」とは限らないため、!error && data の両方をチェックしてから処理を進めるようにしています。
ログインしてみる
デモメールアドレスとパスワードを使っていざログイン!と思ったのに情報が取得されない..(写真撮り忘れちゃった💦)
なぜだ??( ゚Д゚)
・・・profilesテーブルに入力したidとAuthのUsersに入っているidが一致してない!
なるほど。ということでprofilesテーブルのidに対して"auth.uid"を設定する必要がある。supabaseのテーブルからEdit table。「Default value」にauth.uid()を選択する。
→これでユーザー作成時に自動でauth.users.id(UID)が profiles.id に入るようになった!
今回はコピペでidを一致させちゃおっと。(-_-;)
気を取り直してログイン!
実際の画面がこちら↓。これもシンプルに作成しました。
これで無事にマイページ機能を実装することができました!!
🔹詰まったポイントと学び
①client側とuser側
「"useEffect"や"useState"を使っているけど、"use client"を宣言していないため動かせない。これはuseEffect や useState はクライアント(ブラウザ)でしか動かないから。」このあたりの話ちょっと難しい。libフォルダ内でもserverとclientで分けたりしてるけどもっと勉強が必要..。
②コード記載の段階においてTypeScriptの記載方法にまだ慣れていない。
import { } from ""という構造でファイル名の記載の時.tsという拡張子をつけてしまっていたり、exportの記載をしていなくて読み取れていないことがあった。パスの書き方をはじめ正しい記述方法について学習を深めていくべきだと感じた。
✅次回に向けて
- 今回Supabaseを使って「登録された内容でログインし、その情報をプロフィールに表示」するところを実装した。サーバー側のadmin.ts,dev-signupで管理者として情報を記載しメール確認をスキップして作成してみました。
- マイページではauth.uidとprofilesテーブルのidを紐づけることで適切に情報を取得することを学習しました。
それを踏まえて
📌 予告
次回は、マイページの「プロフィール編集フォーム」を実装してみます!
- ユーザーが自分の名前やメールをフロントエンドから入力
- Supabase の
update()
関数を使ってprofiles
テーブルを更新 - フォームのバリデーションには React Hook Form や Zod の活用も予定!
投稿を通して CRUD の “U” の部分をしっかり実装・学習していきます💪
最期までお付き合いいただきありがとうございました!