FirebaseAuthでのユーザー登録時、HASURAにもFirebase側のUIDを保存する

webアプリケーションでのユーザー認証をFirebaseAuthenticationを行い、JWT認証でHASURAとデータ連携するつくりにしています。

「新規ユーザー登録をする際にFIrebaseAuthにも新規登録しつつ、HASURA側にもFIrebaseのUIDを保存して新規のレコードを追加する」という実装を試したのでメモしておきます。

コンポーネント(新規サインアップのフォーム)

必要な箇所だけ書いています。

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> </> ) }
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>) => {
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] )
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),
{
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, } }
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自体はまだ分からないことが多いが、とりあえずこれで動く。

今回はこれまで。ではまた!