Open1

【Next Cognito Amplify】ログイン管理方法

何について書く?

  • ログイン状態の管理方法

内容

まずNG例(冗長化してかつ、Amplifyのログイン情報を取得しない方法)

ポイント:各ページで ログインステートを更新し、その情報により、ヘッダー・フッターの表示制御を行っていた。ログアウトされるとログインステートがfalseになり、ヘッダーなどは非表示にされるとともに各ページに設置されたwithAuthenticatorによりログイン画面に戻る仕組み。

  • ①グローバルステート準備(recoil)
import { atom } from 'recoil'

const loginState = atom({
  key: 'login',
  default: false
})

export default loginState
  • ②グローバルステートの影響範囲を設定(_app.tsx)

Amplify.configure(awsconfig)
const Test = ({ Component, pageProps }: AppProps): JSX.Element => {
const islogin = useRecoilValue(loginState)

  return (
    <>
      <RecoilRoot>
        <Head>
          <title>Test</title>
        </Head>
          {islogin ?
          <>
          <Header />
               <Component {...pageProps} />
          <Footer />
          </>
          :
         <Component {...pageProps} />
          }
      </RecoilRoot>
    </>
  )
}
export default Test
  • ③各ページの記載(index.tsxはじめ、すべてにwithAuthenticatorをつけていた。)
const TestIndex = () => {
   const setLogin = useSetRecoilState(loginState)
  useEffect(() => {
    setLogin(true)
  }
  ,[])
  return (
    <>
      <h1>Test</h1>
    </>
  )
}

export default withAuthenticator(TestIndex)

改善後のベストプラクティス(Amplifyのログイン情報を取得する方法)

上記NGパターンの①②はそのまま残しプラス2つ(ユーザー情報用のグローバルステートとログイン処理用コンポーネントを準備)及び各ページの記載変更を行う。

  • ④ ユーザー情報格納用のグローバルステート
import { atom } from 'recoil'

const userState = atom({
  key: 'user',
  default: {
    userName: ''
  },
})

export default userState
  • ⑤ログイン共通処理(ここでグーグルアナリティクスなどの記載も可能)

export const testAuth = () => {
  const [isLoaded, setIsLoaded] = useState(false) //ステート:読み込み
  const [isLogined, setIsLogined] = useRecoilState(loginState) //グローバルステート:ログイン状態
  const [userInfo, setUserInfo] = useRecoilState(userState) //グローバルステート:ユーザー情報

  useEffect(() => {
    const fetchUserInfo = async () => {
      const userInfo = await Auth.currentUserInfo()

      if (!userInfo) {
        setUserInfo(undefined) //ユーザー無し
        setIsLoaded(true) //読み込みは出来た
        setIsLogined(false) //ログインしていない
        return
      }

      setUserInfo({
        userName: userInfo.username,  //ユーザー情報も格納
      })
      setIsLoaded(true)// 読み込みできた
      setIsLogined(true)// ログインしている
    }

    fetchUserInfo() 
  }, [isLogined]) //ログイン状態が変更されるたび呼ばれる。

  return { isLoaded, userInfo } // 読み込み結果と、ユーザー情報を返す。
}
  • ⑥トップページ からsetLoginの記述削除
const TestIndex = () => {
  useEffect(() => {
  }
  ,[])
  return (
    <>
      <h1>Test</h1>
    </>
  )
}

export default withAuthenticator(TestIndex)
  • ⑦他のページからはwithAuthenticatorをすべて削除 代わりにtestAuthを使用する。
const anotherPage = () => {
  const router = useRouter()
  const { isLoaded, userInfo } = testAuth()

  useEffect(() => {
      if (!isLoaded) return
      if (!userInfo) {
        router.push('/')
        return
      }
  }, [isLoaded, userInfo])

  return (
    <div>
       別ページです。
    </div>
  )
}

export default anotherPage
ログインするとコメントできます