简体   繁体   English

Next.js useSession 和 SessionProvider 的 13 个和下一个身份验证问题

[英]Next.js 13 and next-auth issues with useSession and SessionProvider

I'm trying to make a login page.我正在尝试制作一个登录页面。 on my page.tsx file I get either of two errors depending on if I include "use client";在我的 page.tsx 文件中,我收到两个错误之一,具体取决于我是否包含“使用客户端”; at the top of my code.在我的代码的顶部。 If I don't have "use client";如果我没有“使用客户端”; I get this error: Error: React Context is unavailable in Server Components if I do use "use client";我收到此错误: Error: React Context is unavailable in Server Components I get this error: Error: [next-auth]: useSession must be wrapped in a <SessionProvider />我收到此错误: Error: [next-auth]: useSession must be wrapped in a <SessionProvider />

this is my layout.tsx file:这是我的 layout.tsx 文件:

`import Image from 'next/image'
import { SessionProvider } from "next-auth/react";
import { ReactNode } from "react";
import React from 'react';

import "./globals.css";
import Link from "next/link";

type Props = {
  children: ReactNode;
  session: any;
};

export default function Layout({ children, session }: Props) {
  return (
    <html lang="en">
      <head />
      <body>
        <div className="mx-auto">
          <div className="flex flex-row flex-wrap">
            <aside className="w-full sm:w-1/3 md:w-1/5 xl:w-1/6 border-r-2 border-[#F845C6]">
              <div className="sticky top-0 p-4 w-full">
                <ul className="flex flex-col overflow-hidden">
                  <li className="m-5 text-center">
                    <Link href="login">LOGO</Link>
                  </li>
                  <li className="m-5 text-center">
                    <Link href="/">Dashboard</Link>
                  </li>
                  <li className="m-5 text-center">
                    <Link href="tasks">Tasks</Link>
                  </li>
                  <li className="m-5 text-center">
                    <Link href="reporting">Reporting</Link>
                  </li>
                </ul>
              </div>
            </aside>

            <div className="w-full sm:w-2/3 md:w-4/5 xl:w-5/6">{children}</div>
          </div>
        </div>
      </body>
    </html>
  );
}

export function getLayout(page: any) {
  const { session } = page.props;

  return (
    <SessionProvider session={session}>
      <Layout session={session}>{page}</Layout>
    </SessionProvider>
  );
}
`
this is the login page.tsx file:


`"use client";
import React from 'react'
import { useSession, signIn, signOut } from 'next-auth/react'
import { getLayout } from '../components/Layout'

export default function Login() {
  const { data: session } = useSession();
  console.log(session);

  if (session) {
    return (
      <div style={{ fontFamily: 'sans-serif', margin: '10px 20px' }}>
        <p>Welcome, {session.user.name}</p>
        <img src={session.user.image} alt="" style={{ borderRadius: '15px', width: '80px', margin: '10px' }} />
        <button onClick={() => signOut()}>Sign out</button>
      </div>
    );
  } else {
    return (
      <div>
        <p>Please sign in</p>
        <button onClick={() => signIn("google", { callbackUrl: '/account' })}>Sign in with Google</button>
      </div>
    );
  }
}

Login.getLayout = function getLayout(page: any) {
  return getLayout(page);
};`

Im trying to move from a older project to one tht uses the app directory.我试图从一个旧项目转移到一个使用应用程序目录的项目。 I tried to add the SessionProvider code that was in the original _app.js file to the root layout but Im not having any luck我试图将原始 _app.js 文件中的 SessionProvider 代码添加到根布局,但我没有任何运气

For anyone else encountering this page, and in case you never resolved the issue, The SessionProvider simply needs to be wrapped in a client component which is used in the server-rendered layout, instead of being applied in the layout directly.对于遇到此页面的任何其他人,如果您从未解决过该问题,SessionProvider 只需要包装在服务器呈现布局中使用的客户端组件中,而不是直接应用于布局中。

make a provider file:制作提供者文件:

"use client";

import { SessionProvider } from "next-auth/react";

type Props = {
  children?: React.ReactNode;
};

export const NextAuthProvider = ({ children }: Props) => {
  return <SessionProvider>{children}</SessionProvider>;
};

and then use it in your root layout like so:然后像这样在你的根布局中使用它:

type Props = {
  children: ReactNode;
};

export default function RootLayout({ children }: Props) {
  ...
  return (
    ...
    <NextAuthProvider>
      ...
      {children}
      ...
    </NextAuthProvider>
    ...
  );
}

This will give you access to the session context in all client-side components across the site, which is typically what you would want.这将使您能够访问站点中所有客户端组件中的 session 上下文,这通常是您想要的。

the first issue is the way how you constructed Layout is not recognized.第一个问题是无法识别您构建布局的方式。

export default function Layout({ children, session }: Props) {
  return (
    <html lang="en">
      <head />
      <body>
        {/* after body element place SessionProvider */}
        <SessionProvider>
          <div className="mx-auto">
            {/* then the rest of jsx or components here */}
          </div>
        </SessionProvider>
      </body>
    </html>
  );
}

useSession is a hook and hooks can be used in client components only. useSession是一个钩子,钩子只能在客户端组件中使用。 You either convert your component into a client component by adding a use client directive at the beginning of the file.您可以通过在文件开头添加use client指令将您的组件转换为客户端组件。

Or in server components, you can use getServerSession或者在服务器组件中,您可以使用getServerSession

import { getServerSession } from 'next-auth'
import { NextAuthOptions } from 'next-auth'

export const authOptions: NextAuthOptions = {
  // your options here
}


const session = await getServerSession(authOptions)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM