NextAuth 会话中的故障 NextJS 13

huangapple go评论54阅读模式
英文:

Glitch with NextAuth session NextJS 13

问题

我在我的NextJS 13应用中实现了NextAuth,但是当我重新加载页面时,如果会话尚未被获取,数据首先返回为undefined,然后经过几次尝试后,实际数据(会话)才会被返回。结果,我在UI上看到了一个故障:未登录/已登录为...

export default function RootLayout({ children, session }) {
  return (
    <html>
      <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      </head>
      <body>
        <SessionProvider session={session}>
            <Header />
            {children}
        </SessionProvider>
      </body>
    </html>
  )
}

Auth page:

import { useSession, signIn, signOut } from "next-auth/react"

export default function Component() {
  const { data: session } = useSession()
  if(session) {
    return <>
      Signed in as {session.user.email} <br/>
      <button onClick={() => signOut()}>Sign out</button>
    </>
  }
  return <>
    Not signed in <br/>
    <button onClick={() => signIn()}>Sign in</button>
  </>
}
英文:

I implemented NextAuth in my NextJS 13 app, but when I reload the page, and session hasn't been fetched yet, the data returns as undefined first and then after a few attempts the actual data(session) is getting returned. As result, I see the glitch on UI: Not signed in/ Signed in as ...

export default function RootLayout({ children, session }) {
return (
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<SessionProvider session={session}>
<Header />
{children}
</SessionProvider>
</body>
</html>
)
}

Auth page:

import { useSession, signIn, signOut } from "next-auth/react"
export default function Component() {
const { data: session } = useSession()
if(session) {
return <>
Signed in as {session.user.email} <br/>
<button onClick={() => signOut()}>Sign out</button>
</>
}
return <>
Not signed in <br/>
<button onClick={() => signIn()}>Sign in</button>
</>
}

答案1

得分: 0

因为没有可用的数据,会话将被设置为未定义。所以你需要使用状态来查看数据是否被获取。useSession() 钩子函数为你返回状态。

如果你想要在客户端实现无缝体验,可以按照以下方式进行。

import { useSession, signIn, signOut } from "next-auth/react"

export default function Component() {
  const { data: session, status } = useSession()
  
  // 注意:这不是强制性的。只有在需要在获取数据之前显示加载状态时才使用
  if (status === "loading") {
    return <p>Loading...</p>
  }

  if (status === "unauthenticated") {
   return <>
    Not signed in <br/>
      <button onClick={() => signIn()}>Sign in</button>
    </>
  }

  return <>
      Signed in as {session.user.email} <br/>
      <button onClick={() => signOut()}>Sign out</button>
   </>
  
}

如果你需要在服务器端实现这个功能,可以采用以下方法。

import { getServerSession } from "next-auth/next"
import { useSession, signIn, signOut } from "next-auth/react"
import { authOptions } from "./api/auth/[...nextauth]"

export default function Component() {
  const { data: session } = useSession()

  if (typeof window === "undefined") return null
  
  if(session) {
    return <>
      Signed in as {session.user.email} <br/>
      <button onClick={() => signOut()}>Sign out</button>
    </>
  }
  
  return <>
    Not signed in <br/>
    <button onClick={() => signIn()}>Sign in</button>
  </>
  
}

export async function getServerSideProps(context) {
  return {
    props: {
      session: await getServerSession(
        context.req,
        context.res,
        authOptions
      ),
    },
  }
}
英文:

As data is not avaialble, session will be undefined. so you need to use the status and see whether data is fetched or not. useSession() hook returns the status for you.

If you want to have a seamless experience in a client-side implementation. you can do as below.

import { useSession, signIn, signOut } from &quot;next-auth/react&quot;

export default function Component() {
  const { data: session, status } = useSession()
  
  // Note: This is not mandatory. Use only if you want to show some kind of loading until you get the data
  if (status === &quot;loading&quot;) {
    return &lt;p&gt;Loading...&lt;/p&gt;
  }

  if (status === &quot;unauthenticated&quot;) {
   return &lt;&gt;
    Not signed in &lt;br/&gt;
      &lt;button onClick={() =&gt; signIn()}&gt;Sign in&lt;/button&gt;
    &lt;/&gt;
  }

  return &lt;&gt;
      Signed in as {session.user.email} &lt;br/&gt;
      &lt;button onClick={() =&gt; signOut()}&gt;Sign out&lt;/button&gt;
   &lt;/&gt;
  
}

if you need to implement this on the server-side, the approach will be this.

import { getServerSession } from &quot;next-auth/next&quot;
import { useSession, signIn, signOut } from &quot;next-auth/react&quot;
import { authOptions } from &quot;./api/auth/[...nextauth]&quot;


export default function Component() {
  const { data: session } = useSession()

  if (typeof window === &quot;undefined&quot;) return null
  
  if(session) {
    return &lt;&gt;
      Signed in as {session.user.email} &lt;br/&gt;
      &lt;button onClick={() =&gt; signOut()}&gt;Sign out&lt;/button&gt;
    &lt;/&gt;
  }
  
  return &lt;&gt;
    Not signed in &lt;br/&gt;
    &lt;button onClick={() =&gt; signIn()}&gt;Sign in&lt;/button&gt;
  &lt;/&gt;
  
}

export async function getServerSideProps(context) {
  return {
    props: {
      session: await getServerSession(
        context.req,
        context.res,
        authOptions
      ),
    },
  }
}

huangapple
  • 本文由 发表于 2023年2月10日 05:32:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75404618.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定