Reactjs aws amplify react和nextjs破坏了我的用户上下文

Reactjs aws amplify react和nextjs破坏了我的用户上下文,reactjs,next.js,amazon-cognito,vercel,amplify,Reactjs,Next.js,Amazon Cognito,Vercel,Amplify,我不知道为什么,但当我将cognito与我自己的自定义用户上下文一起使用时,一切都很好,但一旦我使用了Authenticator高阶组件,它就会破坏我的用户上下文,我一辈子都不知道为什么,甚至不知道如何修复它。我将在下面发布我的用户上下文文件以供参考,并告诉您它在哪里中断 import { Auth } from 'aws-amplify' import {createContext, useState, useEffect, useMemo} from 'react' //TODO must

我不知道为什么,但当我将cognito与我自己的自定义用户上下文一起使用时,一切都很好,但一旦我使用了Authenticator高阶组件,它就会破坏我的用户上下文,我一辈子都不知道为什么,甚至不知道如何修复它。我将在下面发布我的用户上下文文件以供参考,并告诉您它在哪里中断

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>
  )
}
从“aws放大”导入{Auth}
从“react”导入{createContext,useState,useEffect,useMemo}
//TODO必须从头开始重做cognito,并且可能能够保持此用户上下文不变
export const UserContext=createContext(null)
export const UserProvider=({children})=>{
const[user,setUser]=useState(null)
const[userEmail,setUserEmail]=useState(null)
常量[SignError,SetSignError]=useState(false)
useffect(()=>{
//AWS Cognito
Auth.currentAuthenticatedUser()。然后(x=>setUser(x)).catch((err)=>setUser(null))
},[])
常量HandleSignError=()=>{
console.log(签名错误)
}
const login=(用户名、密码)=>{
SignError&&SetSignError(错误)
授权登录(用户名、密码)
.然后(x=>{
设置用户(x)
log('Welcome:'+x.challengeParam.userAttributes.email)
setUserEmail(x.challengeParam.userAttributes.email)
SetSignError(错误)
})
.catch((错误)=>{
console.log(错误代码)
如果(err.code==='UserNotFoundException'| |'NotAuthorizedException'){
err.message='无效的用户名或密码'
SetSignError(真)
console.log(错误消息)
}
})  
}
常量注销=()=>{
Auth.signOut()。然后((x)=>{
setUser(空)
setUserEmail(空)
返回x
})
}
const signup=(用户名、电子邮件、密码)=>{
身份验证注册({用户名、密码、属性:{email})
.然后(x=>{
设置用户(x)
返回x
})
.catch((错误)=>{
如果(错误代码){
err.message='您的用户名或密码不正确'
}
失误
})
}
const vals=useMemo(()=>({user,login,logout,signup,handleSignError,userEmail,signError}),[user,userEmail,signError])
返回(
{儿童}
)
}

在login函数下,它现在返回在我包装组件和
npm I aws amplify react
之后未找到的用户。有趣的是,当我卸载它时,仍然会出现相同的错误,如果不完全删除amplify并再次执行完整的
amplify init
,我就无法返回。更令人困惑的是,我的应用程序托管在vercel上,当我尝试在本地机器上执行此操作后,它就会中断。如果我没有遗漏一些东西,我的应用程序在云端中断了,即使我没有推送修改过的代码,那么我猜当我在本地机器上尝试这样做时,cognito在云端得到了一些东西,然后在vercel上搞砸了我的未触及副本?????从那以后,我也试着使用nextauth,这让我觉得我应该坚持前端工作,或者找到更好的解决方案?任何帮助都将不胜感激。我将恢复到我的旧设置,重新构建我的cognito并从头开始放大,以便再次运行。

在调用身份验证提供程序之前,您需要调用cognito配置。在定义身份验证提供程序或上下文之前放置它

Auth.configure({...your_config})
const UserContext = () => {};
我还在上下文中使用auth钩子,这样就不需要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),
  }
};
您还需要在GetStaticPath、getStaticProps和getServerSideProps中需要访问Congito Auth的每个页面上调用Auth.configure。这是因为它们在构建期间或在服务器上从应用程序独立调用

Auth.configure({...your_config})
const getStaticProps = () => {};
const getStaticPaths = () => {};
const getServerSideProps = () => {};
如果你能用的话,他们的手机相当不错


最后,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})
这是我的工作用户上下文。我删除了注册函数,并将在稍后对其进行操作和测试后添加它

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>
  )
}
从“aws放大”导入{Auth}
从“react”导入{createContext,useState,useEffect,useMemo}
export const UserContext=createContext(null)
export const UserProvider=({children})=>{
const[user,setUser]=useState(null)
const[userEmail,setUserEmail]=useState(null)
常量[SignError,SetSignError]=useState(false)
常量[sub,setSub]=useState(null)
useffect(()=>{
//AWS Cognito
Auth.currentAuthenticatedUser()
.然后(x=>{
setUser(x.username)
setUserEmail(x.attributes.email)
setSub(x.attributes.sub)
})
.catch((错误)=>{
console.log(错误)
setUser(空)
})
},[])
常量HandleSignError=()=>{
console.log(签名错误)
}
const login=(用户名、密码)=>{
SignError&&SetSignError(错误);
授权登录(用户名、密码)
。然后((x)=>{
setUser(x.username)
SetSignError(错误)
console.log(x)
})
.catch((错误)=>{
console.log(错误)
SetSignError(真)
})  
}
常量注销=()=>{
Auth.signOut()。然后((x)=>{
setUser(空)
setUserEmail(空)
setSub(空)
})
}
}
const vals=useMemo(()=>({user,sub,login,logout,handleSignError,userEmail,signError}),[user,userEmail,signError,sub])
返回(
{儿童}
)
}

谢谢你。你的答案和教程让我明白了。