webアプリケーションでのユーザー認証をFirebaseAuthenticationを行い、JWT認証でHASURAとデータ連携するつくりにしています。
「新規ユーザー登録をする際にFIrebaseAuthにも新規登録しつつ、HASURA側にもFIrebaseのUIDを保存して新規のレコードを追加する」という実装を試したのでメモしておきます。
コンポーネント(新規サインアップのフォーム)
必要な箇所だけ書いています。
export const Auth = () => {
const user = firebase.auth().currentUser
} = useFirebaseAuth() //FirebaseAuthでLoginやSignupするカスタムフック
className="mt-8 flex justify-center items-center flex-col"
/* ここにemeilやpasswordのinput */
export const Auth = () => {
const user = firebase.auth().currentUser
const {
authUser,
} = useFirebaseAuth() //FirebaseAuthでLoginやSignupするカスタムフック
return (
<>
<form
onSubmit={authUser}
className="mt-8 flex justify-center items-center flex-col"
>
/* ここにemeilやpasswordのinput */
<button
type="submit"
>
Singup
</button>
</form>
</>
)
}
export const Auth = () => {
const user = firebase.auth().currentUser
const {
authUser,
} = useFirebaseAuth() //FirebaseAuthでLoginやSignupするカスタムフック
return (
<>
<form
onSubmit={authUser}
className="mt-8 flex justify-center items-center flex-col"
>
/* ここにemeilやpasswordのinput */
<button
type="submit"
>
Singup
</button>
</form>
</>
)
}
Signupボタンを押すと認証用のカスタムフックからauthUserが実行されます。
FirebaseAuth新規登録カスタムフック(authUser)
コンポーネントで実行されたauthUserが何をしているか確認。上記とは別ファイルのカスタムフック内の一部を抜粋。
const authUser = useCallback(
async (e: FormEvent<HTMLFormElement>) => {
//ログインフォームから来たときはsignInWithEmailAndPassword
await firebase.auth().signInWithEmailAndPassword(email, password)
//新規登録フォームから来たときはcreateUserWithEmailAndPassword
.createUserWithEmailAndPassword(email, password)
.then((userCredential) => {
//userCredentialから今新規登録したユーザの情報が取れる
firebase_id: userCredential.user.uid,
email: userCredential.user.email,
//ミューテーション用のフックで用意していた'createUserMutation'に必要なパラメータを渡してリクエスト
createUserMutation.mutate(param)
[email, password, isLogin]
const authUser = useCallback(
async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
if (isLogin) {
//ログインフォームから来たときはsignInWithEmailAndPassword
try {
await firebase.auth().signInWithEmailAndPassword(email, password)
} catch (e) {
alert(e.message)
}
resetInput()
} else {
//新規登録フォームから来たときはcreateUserWithEmailAndPassword
try {
await firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then((userCredential) => {
//userCredentialから今新規登録したユーザの情報が取れる
const param = {
firebase_id: userCredential.user.uid,
email: userCredential.user.email,
}
//ミューテーション用のフックで用意していた'createUserMutation'に必要なパラメータを渡してリクエスト
createUserMutation.mutate(param)
})
} catch (e) {
alert(e.message)
}
resetInput()
}
},
[email, password, isLogin]
)
const authUser = useCallback(
async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
if (isLogin) {
//ログインフォームから来たときはsignInWithEmailAndPassword
try {
await firebase.auth().signInWithEmailAndPassword(email, password)
} catch (e) {
alert(e.message)
}
resetInput()
} else {
//新規登録フォームから来たときはcreateUserWithEmailAndPassword
try {
await firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then((userCredential) => {
//userCredentialから今新規登録したユーザの情報が取れる
const param = {
firebase_id: userCredential.user.uid,
email: userCredential.user.email,
}
//ミューテーション用のフックで用意していた'createUserMutation'に必要なパラメータを渡してリクエスト
createUserMutation.mutate(param)
})
} catch (e) {
alert(e.message)
}
resetInput()
}
},
[email, password, isLogin]
)
FirebaseのAPI createUserWithEmailAndPassword を実行。ここでフォームで入力してもらったメールアドレスとパスワードを使う。
.thenすると userCredential というたったいま登録したユーザーの情報が返ってくる。
ここからUIDとメールアドレスを引っ張り出すことが出来ます。
UIDとメールアドレスを使って次はHASURAでユーザーをINSERTするクエリをやっていきます。
そのために別途用意していた createUserMutation は ReactQueryで CREATE_USER というユーザーを新規追加する用の関数です。
HASURA新規登録カスタムフック(createUserMutation)
必要な部分だけ抜粋
import { useEffect } from 'react'
import { useQueryClient, useMutation } from 'react-query'
import { GraphQLClient } from 'graphql-request'
import Cookie from 'universal-cookie'
import {CREATE_USER} from '../queries/queries' //mutationクエリ「CREATE_USER」をqueriesに作っておく
import {CreateUser } from '../types/types' //型も作っておく
import { useDispatch } from 'react-redux'
import { resetEditedTask, resetEditedNews } from '../slices/uiSlice'
const cookie = new Cookie()
let graphQLClient: GraphQLClient
export const useAppMutate = () => {
const queryClient = useQueryClient()
const createUserMutation = useMutation(
(createUser: CreateUser) => graphQLClient.request(CREATE_USER, createUser),
dispatch(resetEditedTask())
import { useEffect } from 'react'
import { useQueryClient, useMutation } from 'react-query'
import { GraphQLClient } from 'graphql-request'
import Cookie from 'universal-cookie'
import {CREATE_USER} from '../queries/queries' //mutationクエリ「CREATE_USER」をqueriesに作っておく
import {CreateUser } from '../types/types' //型も作っておく
import { useDispatch } from 'react-redux'
import { resetEditedTask, resetEditedNews } from '../slices/uiSlice'
const cookie = new Cookie()
let graphQLClient: GraphQLClient
export const useAppMutate = () => {
const queryClient = useQueryClient()
const createUserMutation = useMutation(
(createUser: CreateUser) => graphQLClient.request(CREATE_USER, createUser),
{
onSuccess: (res) => {
console.log(res)
},
onError: () => {
dispatch(resetEditedTask())
},
}
)
return {
createUserMutation,
}
}
import { useEffect } from 'react'
import { useQueryClient, useMutation } from 'react-query'
import { GraphQLClient } from 'graphql-request'
import Cookie from 'universal-cookie'
import {CREATE_USER} from '../queries/queries' //mutationクエリ「CREATE_USER」をqueriesに作っておく
import {CreateUser } from '../types/types' //型も作っておく
import { useDispatch } from 'react-redux'
import { resetEditedTask, resetEditedNews } from '../slices/uiSlice'
const cookie = new Cookie()
let graphQLClient: GraphQLClient
export const useAppMutate = () => {
const queryClient = useQueryClient()
const createUserMutation = useMutation(
(createUser: CreateUser) => graphQLClient.request(CREATE_USER, createUser),
{
onSuccess: (res) => {
console.log(res)
},
onError: () => {
dispatch(resetEditedTask())
},
}
)
return {
createUserMutation,
}
}
ReactQueryの「useMutation」を使い、さらにその中でリクエストを投げる用の graphql-request も使ってCREATE_USERを叩く。そのときにさっきFirebaseからかえってきたユーザーの情報のオブジェクトを、createUserというパラメータにまとめて渡すでOK。
mutationの CREATE_USER はクエリのファイルに作っておき、型も用意しておきましょう。
ReactQueryに慣れていきたい
ReactQuery自体はまだ分からないことが多いが、とりあえずこれで動く。
今回はこれまで。ではまた!