如何在 nextjs 组件中使用 next-auth?

Posted

技术标签:

【中文标题】如何在 nextjs 组件中使用 next-auth?【英文标题】:How do I use next-auth within a nextjs component? 【发布时间】:2022-01-22 12:39:29 【问题描述】:

我正在尝试将我的应用程序拆分为多个组件,并且我正在尝试创建一个仪表板组件,但是,我该如何在组件中实现 next-auth,以前我有 getServerSideProps,但是因为这个是我做不到的组件。

这是我的组件

import 
  SearchIcon,
  BellIcon,
  UserCircleIcon,
  ChevronDownIcon,
  UserIcon,
  LogoutIcon
 from '@heroicons/react/outline';

import  signOut  from 'next-auth/client';

export default function Navigation(...session) 
  return (
    <>
      <div className="py-6 px-8 lg:h-16 lg:flex justify-between items-center bg-blue-700 text-white">
        <div className="flex-1">
          <div className="lg:pr-4 lg:py-4">
            <label htmlFor="search" className="sr-only">
              Search
            </label>

            <div className="relative">
              <div className="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center">
                <SearchIcon className="h-5 w-5 text-white" aria-hidden="true" />
              </div>

              <input
                id="search"
                name="search"
                className="block w-full bg-blue-800 border border-blue-800 rounded-md py-2 pl-10 pr-3 text-sm placeholder-white focus:outline-none focus:ring-1 focus:ring-white focus:border-white sm:text-sm"
                placeholder="Search"
                type="search"
              />
            </div>
          </div>
        </div>

        <div className="relative flex items-center justify-center mt-8 lg:mt-0">
          <div className="relative mr-6">
            <BellIcon className="w-5" />

            <small className="text-xs absolute -top-1 -right-2 -mt-2 bg-red-500 rounded-full py-0.5 px-1.5">
              1
            </small>
          </div>

          <details className="relative">
            <summary className="flex items-center">
              <UserCircleIcon className="w-5 mr-2" />

              <h2>
                session.user.firstname session.user.lastname
              </h2>

              <ChevronDownIcon
                className="ml-2 flex-shrink-0 h-4 w-4 text-blue-200"
                aria-hidden="true"
              />
            </summary>

            <div className="w-full mt-4 pb-4 absolute shadow-lg flex flex-col justify-center px-2 space-y-1 bg-blue-700">
              <Link href="/dashboard/myprofile">
                <a className="bg-blue-800 text-white hover:bg-blue-600 flex items-center px-2 py-2 text-sm font-medium rounded-md">
                  <UserIcon className="w-5 h-5 mr-2" />
                  Profile
                </a>
              </Link>

              <Link href="#">
                <a
                  onClick=signOut
                  className="bg-blue-800 text-white hover:bg-blue-600 flex items-center px-2 py-2 text-sm font-medium rounded-md">
                  <LogoutIcon className="w-5 h-5 mr-2" />
                  Sign out
                </a>
              </Link>
            </div>
          </details>
        </div>
      </div>
    </>
  );

目前我得到的是以下内容

TypeError: Cannot read properties of undefined (reading 'firstname')

编辑#1

这是我的_app.js [已更新]

import Head from 'next/head';
import  Provider  from 'next-auth/client';

// assets
import '../styles/global.css';
import '../javascripts/app.js';

// components
import Footer from './components/Footer';

function MyApp( Component, pageProps ) 
  return (
    <>
      <Head>
        <meta name="theme-color" content="#1E40AF" />
      </Head>

      <section className="flex flex-col min-h-screen">
        <Provider session=pageProps.session>
          <Component ...pageProps className="flex-1" />
        </Provider>
      </section>

      <Footer />
    </>
  );


export default MyApp;

【问题讨论】:

您是否尝试过在组件中使用useSession @juliomalves 我已经尝试过了,但我无法让会话通过 您没有在您的_app 文件中使用SessionProvider 吗? @juliomalves 我已将我的 app.js 文件添加为编辑。 如果您没有从 s-s-r 传递会话,您可能需要在 useEffect 中使用 getSession()​ 来检索它。 【参考方案1】:

为了解决这个问题,我做了以下操作

_app.js - 现在使用提供者在所有页面之间共享会话。

import Head from 'next/head';
import  Provider  from 'next-auth/client';

// assets
import '../styles/global.css';
import '../javascripts/app.js';

// components
import Footer from './components/Footer';

function MyApp( Component, pageProps ) 
  return (
    <>
      <Head>
        <meta name="theme-color" content="#1E40AF" />
      </Head>

      <section className="flex flex-col min-h-screen">
        <Provider session=pageProps.session>
          <Component ...pageProps className="flex-1" />
        </Provider>
      </section>

      <Footer />
    </>
  );


export default MyApp;

对于组件,我现在有以下内容

import 
  SearchIcon,
  BellIcon,
  UserCircleIcon,
  ChevronDownIcon,
  UserIcon,
  LogoutIcon
 from '@heroicons/react/outline';

import  useSession, signOut  from 'next-auth/client';
import Link from 'next/link';

export default function Navigation() 
  const [session, loading] = useSession()

  return (
    <>
      <div className="py-6 px-8 lg:h-16 lg:flex justify-between items-center bg-blue-700 text-white">
        <div className="flex-1">
          <div className="lg:pr-4 lg:py-4">
            <label htmlFor="search" className="sr-only">
              Search
            </label>

            <div className="relative">
              <div className="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center">
                <SearchIcon className="h-5 w-5 text-white" aria-hidden="true" />
              </div>

              <input
                id="search"
                name="search"
                className="block w-full bg-blue-800 border border-blue-800 rounded-md py-2 pl-10 pr-3 text-sm placeholder-white focus:outline-none focus:ring-1 focus:ring-white focus:border-white sm:text-sm"
                placeholder="Search"
                type="search"
              />
            </div>
          </div>
        </div>

        <div className="relative flex items-center justify-center mt-8 lg:mt-0">
          <div className="relative mr-6">
            <BellIcon className="w-5" />

            <small className="text-xs absolute -top-1 -right-2 -mt-2 bg-red-500 rounded-full py-0.5 px-1.5">
              1
            </small>
          </div>

          <details className="relative">
            <summary className="flex items-center">
              <UserCircleIcon className="w-5 mr-2" />

               session &&
                <h2>
                  session.firstname  session.lastname
                </h2>
              

              <ChevronDownIcon
                className="ml-2 flex-shrink-0 h-4 w-4 text-blue-200"
                aria-hidden="true"
              />
            </summary>

            <div className="w-full mt-4 pb-4 absolute shadow-lg flex flex-col justify-center px-2 space-y-1 bg-blue-700">
              <Link href="/dashboard/myprofile">
                <a className="bg-blue-800 text-white hover:bg-blue-600 flex items-center px-2 py-2 text-sm font-medium rounded-md">
                  <UserIcon className="w-5 h-5 mr-2" />
                  Profile
                </a>
              </Link>

              <Link href="#">
                <a
                  onClick=signOut
                  className="bg-blue-800 text-white hover:bg-blue-600 flex items-center px-2 py-2 text-sm font-medium rounded-md">
                  <LogoutIcon className="w-5 h-5 mr-2" />
                  Sign out
                </a>
              </Link>
            </div>
          </details>
        </div>
      </div>
    </>
  );

【讨论】:

以上是关于如何在 nextjs 组件中使用 next-auth?的主要内容,如果未能解决你的问题,请参考以下文章

Nextjs:如何使用具有多个值的 ContextAPI,所有这些值都需要从子组件中更新

使用nextjs切换页面时如何只更改一个组件?

NextJs中如何通过多层组件传递href值?

如何将道具从组件传递到 NextJS 中的 getServerSideProps()?

如何在 NextJS 中更新 <Image /> 标签的 src 而无需重新渲染整个组件

如何在 nextjs 中使用没有 css 模块的 scss