簡體   English   中英

aws-amplify-react 和 nextjs 破壞了我的用戶上下文

[英]aws-amplify-react and nextjs breaks my user context

我不知道為什么,但是當我將 cognito 與我自己的自定義用戶上下文一起使用時,一切正常,但是一旦我使用 withAuthenticator 高階組件,它就會破壞我的用戶上下文,我終生無法弄清楚為什么,甚至如何要解決這個問題。 我將在下面發布我的用戶上下文文件以供參考,並告訴您它在哪里中斷。

import { Auth } from 'aws-amplify'
import {createContext, useState, useEffect, useMemo} from 'react'

//TODO must redo cognito from scratch and will probably be able to keep this user context untouched

export const UserContext = createContext(null)

export const UserProvider = ({children}) => {
  
  const [ user, setUser ] = useState(null)
  const [ userEmail, setUserEmail ] = useState(null)
  const [ signInError, setSignInError ] = useState(false)

  useEffect(()=>{
    // AWS Cognito
    Auth.currentAuthenticatedUser().then(x=>setUser(x)).catch((err)=>setUser(null))
  },[])

   const handleSignInError = () => {
    console.log(signInError)
  }

  const login = (username, password) => {
    signInError && setSignInError(false)
    Auth.signIn(username, password)
    .then( x => {
      setUser(x)
      console.log('Welcome: ' + x.challengeParam.userAttributes.email)
      setUserEmail(x.challengeParam.userAttributes.email)
      setSignInError(false)
    })
    .catch((err)=>{
      console.log(err.code)
      if(err.code === 'UserNotFoundException' || 'NotAuthorizedException'){
        err.message = 'Invalid username or password'
        setSignInError(true)
        console.log(err.message)
      }
    })  
  }
  
  const logout = () => {
    Auth.signOut().then((x)=>{
      setUser(null)
      setUserEmail(null)
      return x
    })
  }

  const signup = (username, email, password) => {
    Auth.signUp({ username, password, attributes: { email } })
    .then( x => {
      setUser(x)
      return x
    })
    .catch((err)=>{
      if(err.code){
        err.message = 'Your Username or Password was incorrect'
      }
      throw err
    })
  }
  
  const vals = useMemo( () => ({user, login, logout, signup, handleSignInError, userEmail, signInError}), [user, userEmail, signInError])
  
  return(
    <UserContext.Provider value={vals}>
      {children}
    </UserContext.Provider>
  )
}

在登錄 function 下,它現在返回在我包裝組件和npm i aws-amplify-react后未找到的用戶。 有趣的是,當我卸載它時,我仍然遇到相同的錯誤,並且在沒有完全刪除放大並再次完成完整的amplify init的情況下無法返回 go。 更令人困惑的是,我的應用程序托管在 vercel 上,並且在我嘗試在本地計算機上執行此操作后中斷。 如果我沒有遺漏任何東西並且我的應用程序確實在雲中中斷,即使我沒有推送我修改過的代碼,那么我猜測 cognito 在我的本地機器上嘗試這個然后在 vercel 上搞砸我未觸及的副本時會在雲中得到一些東西? ??? 從那以后,我還嘗試使用 next-auth,這讓我覺得我應該堅持前端工作還是找到更好的解決方案? 任何幫助,將不勝感激。 生病恢復到我的舊設置並重建我的認知並從頭開始放大只是為了讓它再次運行。

您需要在調用您的身份驗證提供程序之前調用 Cognito 配置。 在定義身份驗證提供程序或上下文之前放置它。

Auth.configure({...your_config})
const UserContext = () => {};

我還在上下文中使用了身份驗證鈎子,從而消除了對 HOC 的需求。

import { useContext } from 'react';
export const useAuth = () => useContext(UserContext);

// use it in components and pages
const user = useAuth();

確保您的配置使用所有正確的類型。 如果你不這樣做,它有時會默默地失敗。 例如,ENV 文件始終作為字符串傳遞,因此必須將某些選項轉換為正確的類型,例如 cookie expires

{
  authenticationFlowType: 'USER_SRP_AUTH',
  cookieStorage: {
    ...other settings
    expires: Number(process.env.NEXT_PUBLIC_COGNITO_COOKIE_EXPIRES),
  }
};

您還需要在 getStaticPaths、getStaticProps 和 getServerSideProps 中需要訪問 Congito auth 的每個頁面上調用 Auth.configure。 這是因為它們是在構建期間或在服務器上從您的應用程序中獨立調用的。

Auth.configure({...your_config})
const getStaticProps = () => {};
const getStaticPaths = () => {};
const getServerSideProps = () => {};

如果你可以使用它,他們托管的 UI非常好。

最后,AWS 有一些用於 Amplify 的庫,我使用@aws-amplify/auth - 我不知道這是否會有所作為。

我將配置文件添加到我的 _app.js 並設置 ssr: true 用於 ssr 身份驗證

import Amplify from 'aws-amplify'
import config from '../src/aws-exports'

Amplify.configure({...config, ssr: true})

這是我的工作用戶上下文。 我刪除了注冊 function 並且稍后會在我處理它並對其進行測試后添加它。

import { Auth } from 'aws-amplify'
import {createContext, useState, useEffect, useMemo} from 'react'

export const UserContext = createContext(null)

export const UserProvider = ({children}) => {
  
  const [ user, setUser ] = useState(null)
  const [ userEmail, setUserEmail ] = useState(null)
  const [ signInError, setSignInError ] = useState(false)
  const [sub, setSub] = useState(null)
  useEffect(()=>{
    // AWS Cognito
    Auth.currentAuthenticatedUser()
      .then(x=>{
        setUser(x.username)
        setUserEmail(x.attributes.email)
        setSub(x.attributes.sub)
      })
      .catch((err)=>{
        console.log(err)
        setUser(null)
      })
  },[])

   const handleSignInError = () => {
    console.log(signInError)
  }

  const login = (username, password) => {
    signInError && setSignInError(false);
    Auth.signIn(username, password)
      .then((x) => {
        setUser(x.username)
        setSignInError(false)
        console.log(x)
      })
      .catch((err)=>{
        console.log(err)    
        setSignInError(true)
      })  
  }
  
  const logout = () => {
    Auth.signOut().then((x)=>{
      setUser(null)
      setUserEmail(null)
      setSub(null)
    })
  }

  
  }
  
  const vals = useMemo( () => ({user, sub, login, logout, handleSignInError, userEmail, signInError}), [user, userEmail, signInError, sub])
  
  return(
    <UserContext.Provider value={vals}>
      {children}
    </UserContext.Provider>
  )
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM