React(Javascript & Typescript)でgoogleアカウント認証を行うカスタムhookを作成する



reactでgoogleアカウント認証を実装しする必要があったので、作成したコードを備忘録として残します。
gapiのauth2から返ってくるtokenIDを管理するためのカスタムhookを作成しました。


## Javascript版reactでの実装

```javascript
import { useEffect, useState } from 'react';

const useGoogleAuth = () => {
  const [isSignedIn, setIsSignedIn] = useState(null);
  const [authInstance, setAuthInstance] = useState(null);
  const [tokenId, setTokenId] = useState(null);

  useEffect(() => {
    const initAuth = async () => {
      const gapi = window.gapi;

      await gapi.load('auth2', async () => {
        const auth2 = await gapi.auth2.init({
          client_id: 'YOUR_CLIENT_ID',
        });

        setAuthInstance(auth2);

        const isSignedIn = auth2.isSignedIn.get();
        setIsSignedIn(isSignedIn);

        if (isSignedIn) {
          const user = auth2.currentUser.get();
          const token = user.getAuthResponse().id_token;
          setTokenId(token);
        }
      });
    };

    initAuth();
  }, []);

  const handleSignIn = async () => {
    const user = await authInstance.signIn();
    setIsSignedIn(true);

    const token = user.getAuthResponse().id_token;
    setTokenId(token);
  };

  const handleSignOut = async () => {
    await authInstance.signOut();
    setIsSignedIn(false);
    setTokenId(null);
  };

  return {
    isSignedIn,
    tokenId,
    handleSignIn,
    handleSignOut,
  };
};

export default useGoogleAuth;
```

以上がReactでGoogleアカウント認証を実装するためのカスタムフックです。このフックを使用することで、gapiのauth2から返ってくるtokenIDを管理できます。



このフックを使用するには、以下のように呼び出します。

```javascript
import useGoogleAuth from './useGoogleAuth';

const MyComponent = () => {
  const { isSignedIn, tokenId, handleSignIn, handleSignOut } = useGoogleAuth();

  // 以下、必要な処理を記述
};
```
このフックを使用することで、isSignedInプロパティでサインインしているかどうかを確認し、tokenIdプロパティで取得したトークンIDを管理することができます。また、handleSignInとhandleSignOut関数を使用して、サインインおよびサインアウトのアクションをトリガーすることができます。




## TypeScriptでの実装

同じ実装をTypeScriptで行うと下記のようになります。

```typescript
import { useEffect, useState } from 'react';

interface IGoogleAuth {
  isSignedIn: boolean | null;
  tokenId: string | null;
  handleSignIn: () => Promise<void>;
  handleSignOut: () => Promise<void>;
}

const useGoogleAuth = (): IGoogleAuth => {
  const [isSignedIn, setIsSignedIn] = useState<boolean | null>(null);
  const [authInstance, setAuthInstance] = useState<gapi.auth2.GoogleAuth | null>(
    null
  );
  const [tokenId, setTokenId] = useState<string | null>(null);

  useEffect(() => {
    const initAuth = async () => {
      const gapi = window.gapi;

      await gapi.load('auth2', async () => {
        const auth2 = await gapi.auth2.init({
          client_id: 'YOUR_CLIENT_ID',
        });

        setAuthInstance(auth2);

        const isSignedIn = auth2.isSignedIn.get();
        setIsSignedIn(isSignedIn);

        if (isSignedIn) {
          const user = auth2.currentUser.get();
          const token = user.getAuthResponse().id_token;
          setTokenId(token);
        }
      });
    };

    initAuth();
  }, []);

  const handleSignIn = async () => {
    const user = await authInstance?.signIn();
    setIsSignedIn(true);

    const token = user?.getAuthResponse().id_token;
    setTokenId(token || null);
  };

  const handleSignOut = async () => {
    await authInstance?.signOut();
    setIsSignedIn(false);
    setTokenId(null);
  };

  return {
    isSignedIn,
    tokenId,
    handleSignIn,
    handleSignOut,
  };
};

export default useGoogleAuth;
```


このフックを使用するには、以下のように呼び出します。


```typescript
import useGoogleAuth from './useGoogleAuth';

const MyComponent = () => {
  const { isSignedIn, tokenId, handleSignIn, handleSignOut } = useGoogleAuth();

  // 以下、必要な処理を記述
};
```
TypeScriptを使用することで、より安全で保守性の高いコードを書くことができますね。

## 参考になる書籍など
・[TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発](https://amzn.to/3obuCmO)
・[モダンJavaScriptの基本から始める React実践の教科書](https://amzn.to/3o97CoI)
・[React(v18)完全入門ガイド｜Hooks、Next.js、Redux、TypeScript](https://click.linksynergy.com/deeplink?id=Qw*xM8wv/u4&mid=47984&murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Freact-complete-guide%2F)